blob: 6fa6de2b6ad586d933945f74de0bc79ef8691664 [file] [log] [blame]
Thomas Gleixner2025cf92019-05-29 07:18:02 -07001// SPDX-License-Identifier: GPL-2.0-only
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002/*
David Woodhouseea8ea462014-03-05 17:09:32 +00003 * Copyright © 2006-2014 Intel Corporation.
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004 *
David Woodhouseea8ea462014-03-05 17:09:32 +00005 * Authors: David Woodhouse <dwmw2@infradead.org>,
6 * Ashok Raj <ashok.raj@intel.com>,
7 * Shaohua Li <shaohua.li@intel.com>,
8 * Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>,
9 * Fenghua Yu <fenghua.yu@intel.com>
Joerg Roedel9f10e5b2015-06-12 09:57:06 +020010 * Joerg Roedel <jroedel@suse.de>
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -070011 */
12
Joerg Roedel9f10e5b2015-06-12 09:57:06 +020013#define pr_fmt(fmt) "DMAR: " fmt
Bjorn Helgaas932a6522019-02-08 16:06:00 -060014#define dev_fmt(fmt) pr_fmt(fmt)
Joerg Roedel9f10e5b2015-06-12 09:57:06 +020015
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -070016#include <linux/init.h>
17#include <linux/bitmap.h>
mark gross5e0d2a62008-03-04 15:22:08 -080018#include <linux/debugfs.h>
Paul Gortmaker54485c32011-10-29 10:26:25 -040019#include <linux/export.h>
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -070020#include <linux/slab.h>
21#include <linux/irq.h>
22#include <linux/interrupt.h>
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -070023#include <linux/spinlock.h>
24#include <linux/pci.h>
25#include <linux/dmar.h>
26#include <linux/dma-mapping.h>
27#include <linux/mempool.h>
Jiang Liu75f05562014-02-19 14:07:37 +080028#include <linux/memory.h>
Omer Pelegaa473242016-04-20 11:33:02 +030029#include <linux/cpu.h>
mark gross5e0d2a62008-03-04 15:22:08 -080030#include <linux/timer.h>
Dan Williamsdfddb962015-10-09 18:16:46 -040031#include <linux/io.h>
Kay, Allen M38717942008-09-09 18:37:29 +030032#include <linux/iova.h>
Joerg Roedel5d450802008-12-03 14:52:32 +010033#include <linux/iommu.h>
Kay, Allen M38717942008-09-09 18:37:29 +030034#include <linux/intel-iommu.h>
Rafael J. Wysocki134fac32011-03-23 22:16:14 +010035#include <linux/syscore_ops.h>
Shane Wang69575d32009-09-01 18:25:07 -070036#include <linux/tboot.h>
Stephen Rothwelladb2fe02009-08-31 15:24:23 +100037#include <linux/dmi.h>
Joerg Roedel5cdede22011-04-04 15:55:18 +020038#include <linux/pci-ats.h>
Tejun Heo0ee332c2011-12-08 10:22:09 -080039#include <linux/memblock.h>
Akinobu Mita36746432014-06-04 16:06:51 -070040#include <linux/dma-contiguous.h>
Christoph Hellwigfec777c2018-03-19 11:38:15 +010041#include <linux/dma-direct.h>
Joerg Roedel091d42e2015-06-12 11:56:10 +020042#include <linux/crash_dump.h>
Anshuman Khandual98fa15f2019-03-05 15:42:58 -080043#include <linux/numa.h>
Lu Baolucfb94a32019-09-06 14:14:52 +080044#include <linux/swiotlb.h>
Suresh Siddha8a8f4222012-03-30 11:47:08 -070045#include <asm/irq_remapping.h>
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -070046#include <asm/cacheflush.h>
FUJITA Tomonori46a7fa22008-07-11 10:23:42 +090047#include <asm/iommu.h>
Lu Baolucfb94a32019-09-06 14:14:52 +080048#include <trace/events/intel_iommu.h>
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -070049
Joerg Roedel078e1ee2012-09-26 12:44:43 +020050#include "irq_remapping.h"
Lu Baolu56283172018-07-14 15:46:54 +080051#include "intel-pasid.h"
Joerg Roedel078e1ee2012-09-26 12:44:43 +020052
Fenghua Yu5b6985c2008-10-16 18:02:32 -070053#define ROOT_SIZE VTD_PAGE_SIZE
54#define CONTEXT_SIZE VTD_PAGE_SIZE
55
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -070056#define IS_GFX_DEVICE(pdev) ((pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY)
David Woodhouse18436af2015-03-25 15:05:47 +000057#define IS_USB_DEVICE(pdev) ((pdev->class >> 8) == PCI_CLASS_SERIAL_USB)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -070058#define IS_ISA_DEVICE(pdev) ((pdev->class >> 8) == PCI_CLASS_BRIDGE_ISA)
David Woodhousee0fc7e02009-09-30 09:12:17 -070059#define IS_AZALIA(pdev) ((pdev)->vendor == 0x8086 && (pdev)->device == 0x3a3e)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -070060
61#define IOAPIC_RANGE_START (0xfee00000)
62#define IOAPIC_RANGE_END (0xfeefffff)
63#define IOVA_START_ADDR (0x1000)
64
Sohil Mehta5e3b4a12017-12-20 11:59:24 -080065#define DEFAULT_DOMAIN_ADDRESS_WIDTH 57
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -070066
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -070067#define MAX_AGAW_WIDTH 64
Jiang Liu5c645b32014-01-06 14:18:12 +080068#define MAX_AGAW_PFN_WIDTH (MAX_AGAW_WIDTH - VTD_PAGE_SHIFT)
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -070069
David Woodhouse2ebe3152009-09-19 07:34:04 -070070#define __DOMAIN_MAX_PFN(gaw) ((((uint64_t)1) << (gaw-VTD_PAGE_SHIFT)) - 1)
71#define __DOMAIN_MAX_ADDR(gaw) ((((uint64_t)1) << gaw) - 1)
72
73/* We limit DOMAIN_MAX_PFN to fit in an unsigned long, and DOMAIN_MAX_ADDR
74 to match. That way, we can use 'unsigned long' for PFNs with impunity. */
75#define DOMAIN_MAX_PFN(gaw) ((unsigned long) min_t(uint64_t, \
76 __DOMAIN_MAX_PFN(gaw), (unsigned long)-1))
77#define DOMAIN_MAX_ADDR(gaw) (((uint64_t)__DOMAIN_MAX_PFN(gaw)) << VTD_PAGE_SHIFT)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -070078
Robin Murphy1b722502015-01-12 17:51:15 +000079/* IO virtual address start page frame number */
80#define IOVA_START_PFN (1)
81
Mark McLoughlinf27be032008-11-20 15:49:43 +000082#define IOVA_PFN(addr) ((addr) >> PAGE_SHIFT)
mark gross5e0d2a62008-03-04 15:22:08 -080083
Andrew Mortondf08cdc2010-09-22 13:05:11 -070084/* page table handling */
85#define LEVEL_STRIDE (9)
86#define LEVEL_MASK (((u64)1 << LEVEL_STRIDE) - 1)
87
Ohad Ben-Cohen6d1c56a2011-11-10 11:32:30 +020088/*
89 * This bitmap is used to advertise the page sizes our hardware support
90 * to the IOMMU core, which will then use this information to split
91 * physically contiguous memory regions it is mapping into page sizes
92 * that we support.
93 *
94 * Traditionally the IOMMU core just handed us the mappings directly,
95 * after making sure the size is an order of a 4KiB page and that the
96 * mapping has natural alignment.
97 *
98 * To retain this behavior, we currently advertise that we support
99 * all page sizes that are an order of 4KiB.
100 *
101 * If at some point we'd like to utilize the IOMMU core's new behavior,
102 * we could change this to advertise the real page sizes we support.
103 */
104#define INTEL_IOMMU_PGSIZES (~0xFFFUL)
105
Andrew Mortondf08cdc2010-09-22 13:05:11 -0700106static inline int agaw_to_level(int agaw)
107{
108 return agaw + 2;
109}
110
111static inline int agaw_to_width(int agaw)
112{
Jiang Liu5c645b32014-01-06 14:18:12 +0800113 return min_t(int, 30 + agaw * LEVEL_STRIDE, MAX_AGAW_WIDTH);
Andrew Mortondf08cdc2010-09-22 13:05:11 -0700114}
115
116static inline int width_to_agaw(int width)
117{
Jiang Liu5c645b32014-01-06 14:18:12 +0800118 return DIV_ROUND_UP(width - 30, LEVEL_STRIDE);
Andrew Mortondf08cdc2010-09-22 13:05:11 -0700119}
120
121static inline unsigned int level_to_offset_bits(int level)
122{
123 return (level - 1) * LEVEL_STRIDE;
124}
125
126static inline int pfn_level_offset(unsigned long pfn, int level)
127{
128 return (pfn >> level_to_offset_bits(level)) & LEVEL_MASK;
129}
130
131static inline unsigned long level_mask(int level)
132{
133 return -1UL << level_to_offset_bits(level);
134}
135
136static inline unsigned long level_size(int level)
137{
138 return 1UL << level_to_offset_bits(level);
139}
140
141static inline unsigned long align_to_level(unsigned long pfn, int level)
142{
143 return (pfn + level_size(level) - 1) & level_mask(level);
144}
David Woodhousefd18de52009-05-10 23:57:41 +0100145
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100146static inline unsigned long lvl_to_nr_pages(unsigned int lvl)
147{
Jiang Liu5c645b32014-01-06 14:18:12 +0800148 return 1 << min_t(int, (lvl - 1) * LEVEL_STRIDE, MAX_AGAW_PFN_WIDTH);
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100149}
150
David Woodhousedd4e8312009-06-27 16:21:20 +0100151/* VT-d pages must always be _smaller_ than MM pages. Otherwise things
152 are never going to work. */
153static inline unsigned long dma_to_mm_pfn(unsigned long dma_pfn)
154{
155 return dma_pfn >> (PAGE_SHIFT - VTD_PAGE_SHIFT);
156}
157
158static inline unsigned long mm_to_dma_pfn(unsigned long mm_pfn)
159{
160 return mm_pfn << (PAGE_SHIFT - VTD_PAGE_SHIFT);
161}
162static inline unsigned long page_to_dma_pfn(struct page *pg)
163{
164 return mm_to_dma_pfn(page_to_pfn(pg));
165}
166static inline unsigned long virt_to_dma_pfn(void *p)
167{
168 return page_to_dma_pfn(virt_to_page(p));
169}
170
Weidong Hand9630fe2008-12-08 11:06:32 +0800171/* global iommu list, set NULL for ignored DMAR units */
172static struct intel_iommu **g_iommus;
173
David Woodhousee0fc7e02009-09-30 09:12:17 -0700174static void __init check_tylersburg_isoch(void);
David Woodhouse9af88142009-02-13 23:18:03 +0000175static int rwbf_quirk;
176
Mark McLoughlin46b08e12008-11-20 15:49:44 +0000177/*
Joseph Cihulab7792602011-05-03 00:08:37 -0700178 * set to 1 to panic kernel if can't successfully enable VT-d
179 * (used when kernel is launched w/ TXT)
180 */
181static int force_on = 0;
Shaohua Libfd20f12017-04-26 09:18:35 -0700182int intel_iommu_tboot_noforce;
Lu Baolu89a60792018-10-23 15:45:01 +0800183static int no_platform_optin;
Joseph Cihulab7792602011-05-03 00:08:37 -0700184
Mark McLoughlin46b08e12008-11-20 15:49:44 +0000185#define ROOT_ENTRY_NR (VTD_PAGE_SIZE/sizeof(struct root_entry))
Mark McLoughlin46b08e12008-11-20 15:49:44 +0000186
Joerg Roedel091d42e2015-06-12 11:56:10 +0200187/*
188 * Take a root_entry and return the Lower Context Table Pointer (LCTP)
189 * if marked present.
190 */
191static phys_addr_t root_entry_lctp(struct root_entry *re)
192{
193 if (!(re->lo & 1))
194 return 0;
Mark McLoughlin46b08e12008-11-20 15:49:44 +0000195
Joerg Roedel091d42e2015-06-12 11:56:10 +0200196 return re->lo & VTD_PAGE_MASK;
197}
198
199/*
200 * Take a root_entry and return the Upper Context Table Pointer (UCTP)
201 * if marked present.
202 */
203static phys_addr_t root_entry_uctp(struct root_entry *re)
204{
205 if (!(re->hi & 1))
206 return 0;
207
208 return re->hi & VTD_PAGE_MASK;
209}
Mark McLoughlin7a8fc252008-11-20 15:49:45 +0000210
Joerg Roedelcf484d02015-06-12 12:21:46 +0200211static inline void context_clear_pasid_enable(struct context_entry *context)
212{
213 context->lo &= ~(1ULL << 11);
214}
215
216static inline bool context_pasid_enabled(struct context_entry *context)
217{
218 return !!(context->lo & (1ULL << 11));
219}
220
221static inline void context_set_copied(struct context_entry *context)
222{
223 context->hi |= (1ull << 3);
224}
225
226static inline bool context_copied(struct context_entry *context)
227{
228 return !!(context->hi & (1ULL << 3));
229}
230
231static inline bool __context_present(struct context_entry *context)
Mark McLoughlinc07e7d22008-11-21 16:54:46 +0000232{
233 return (context->lo & 1);
234}
Joerg Roedelcf484d02015-06-12 12:21:46 +0200235
Sohil Mehta26b86092018-09-11 17:11:36 -0700236bool context_present(struct context_entry *context)
Joerg Roedelcf484d02015-06-12 12:21:46 +0200237{
238 return context_pasid_enabled(context) ?
239 __context_present(context) :
240 __context_present(context) && !context_copied(context);
241}
242
Mark McLoughlinc07e7d22008-11-21 16:54:46 +0000243static inline void context_set_present(struct context_entry *context)
244{
245 context->lo |= 1;
246}
247
248static inline void context_set_fault_enable(struct context_entry *context)
249{
250 context->lo &= (((u64)-1) << 2) | 1;
251}
252
Mark McLoughlinc07e7d22008-11-21 16:54:46 +0000253static inline void context_set_translation_type(struct context_entry *context,
254 unsigned long value)
255{
256 context->lo &= (((u64)-1) << 4) | 3;
257 context->lo |= (value & 3) << 2;
258}
259
260static inline void context_set_address_root(struct context_entry *context,
261 unsigned long value)
262{
Li, Zhen-Hua1a2262f2014-11-05 15:30:19 +0800263 context->lo &= ~VTD_PAGE_MASK;
Mark McLoughlinc07e7d22008-11-21 16:54:46 +0000264 context->lo |= value & VTD_PAGE_MASK;
265}
266
267static inline void context_set_address_width(struct context_entry *context,
268 unsigned long value)
269{
270 context->hi |= value & 7;
271}
272
273static inline void context_set_domain_id(struct context_entry *context,
274 unsigned long value)
275{
276 context->hi |= (value & ((1 << 16) - 1)) << 8;
277}
278
Joerg Roedeldbcd8612015-06-12 12:02:09 +0200279static inline int context_domain_id(struct context_entry *c)
280{
281 return((c->hi >> 8) & 0xffff);
282}
283
Mark McLoughlinc07e7d22008-11-21 16:54:46 +0000284static inline void context_clear_entry(struct context_entry *context)
285{
286 context->lo = 0;
287 context->hi = 0;
288}
Mark McLoughlin7a8fc252008-11-20 15:49:45 +0000289
Mark McLoughlin622ba122008-11-20 15:49:46 +0000290/*
Fenghua Yu2c2e2c32009-06-19 13:47:29 -0700291 * This domain is a statically identity mapping domain.
292 * 1. This domain creats a static 1:1 mapping to all usable memory.
293 * 2. It maps to each iommu if successful.
294 * 3. Each iommu mapps to this domain if successful.
295 */
David Woodhouse19943b02009-08-04 16:19:20 +0100296static struct dmar_domain *si_domain;
297static int hw_pass_through = 1;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -0700298
Fenghua Yu2c2e2c32009-06-19 13:47:29 -0700299/* si_domain contains mulitple devices */
Lu Baolufa954e62019-05-25 13:41:28 +0800300#define DOMAIN_FLAG_STATIC_IDENTITY BIT(0)
Fenghua Yu2c2e2c32009-06-19 13:47:29 -0700301
Lu Baolu942067f2019-05-25 13:41:29 +0800302/*
303 * This is a DMA domain allocated through the iommu domain allocation
304 * interface. But one or more devices belonging to this domain have
305 * been chosen to use a private domain. We should avoid to use the
306 * map/unmap/iova_to_phys APIs on it.
307 */
308#define DOMAIN_FLAG_LOSE_CHILDREN BIT(1)
309
Lu Baolua1948f22020-01-02 08:18:14 +0800310/*
311 * When VT-d works in the scalable mode, it allows DMA translation to
312 * happen through either first level or second level page table. This
313 * bit marks that the DMA translation for the domain goes through the
314 * first level page table, otherwise, it goes through the second level.
315 */
316#define DOMAIN_FLAG_USE_FIRST_LEVEL BIT(2)
317
Lu Baolu2cd13112020-01-02 08:18:15 +0800318/*
319 * Domain represents a virtual machine which demands iommu nested
320 * translation mode support.
321 */
322#define DOMAIN_FLAG_NESTING_MODE BIT(3)
323
Joerg Roedel29a27712015-07-21 17:17:12 +0200324#define for_each_domain_iommu(idx, domain) \
325 for (idx = 0; idx < g_num_of_iommus; idx++) \
326 if (domain->iommu_refcnt[idx])
327
Jiang Liub94e4112014-02-19 14:07:25 +0800328struct dmar_rmrr_unit {
329 struct list_head list; /* list of rmrr units */
330 struct acpi_dmar_header *hdr; /* ACPI header */
331 u64 base_address; /* reserved base address*/
332 u64 end_address; /* reserved end address */
David Woodhouse832bd852014-03-07 15:08:36 +0000333 struct dmar_dev_scope *devices; /* target devices */
Jiang Liub94e4112014-02-19 14:07:25 +0800334 int devices_cnt; /* target device count */
335};
336
337struct dmar_atsr_unit {
338 struct list_head list; /* list of ATSR units */
339 struct acpi_dmar_header *hdr; /* ACPI header */
David Woodhouse832bd852014-03-07 15:08:36 +0000340 struct dmar_dev_scope *devices; /* target devices */
Jiang Liub94e4112014-02-19 14:07:25 +0800341 int devices_cnt; /* target device count */
342 u8 include_all:1; /* include all ports */
343};
344
345static LIST_HEAD(dmar_atsr_units);
346static LIST_HEAD(dmar_rmrr_units);
347
348#define for_each_rmrr_units(rmrr) \
349 list_for_each_entry(rmrr, &dmar_rmrr_units, list)
350
mark gross5e0d2a62008-03-04 15:22:08 -0800351/* bitmap for indexing intel_iommus */
mark gross5e0d2a62008-03-04 15:22:08 -0800352static int g_num_of_iommus;
353
Jiang Liu92d03cc2014-02-19 14:07:28 +0800354static void domain_exit(struct dmar_domain *domain);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700355static void domain_remove_dev_info(struct dmar_domain *domain);
Bjorn Helgaas71753232019-02-08 16:06:15 -0600356static void dmar_remove_one_dev_info(struct device *dev);
Joerg Roedel127c7612015-07-23 17:44:46 +0200357static void __dmar_remove_one_dev_info(struct device_domain_info *info);
Lu Baolu0ce4a852019-08-26 16:50:56 +0800358static void domain_context_clear(struct intel_iommu *iommu,
359 struct device *dev);
Jiang Liu2a46ddf2014-07-11 14:19:30 +0800360static int domain_detach_iommu(struct dmar_domain *domain,
361 struct intel_iommu *iommu);
Lu Baolu4de354e2019-05-25 13:41:27 +0800362static bool device_is_rmrr_locked(struct device *dev);
Lu Baolu8af46c72019-05-25 13:41:32 +0800363static int intel_iommu_attach_device(struct iommu_domain *domain,
364 struct device *dev);
Lu Baolucfb94a32019-09-06 14:14:52 +0800365static phys_addr_t intel_iommu_iova_to_phys(struct iommu_domain *domain,
366 dma_addr_t iova);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700367
Suresh Siddhad3f13812011-08-23 17:05:25 -0700368#ifdef CONFIG_INTEL_IOMMU_DEFAULT_ON
Kyle McMartin0cd5c3c2009-02-04 14:29:19 -0800369int dmar_disabled = 0;
370#else
371int dmar_disabled = 1;
Lu Baolu04618252020-01-02 08:18:02 +0800372#endif /* CONFIG_INTEL_IOMMU_DEFAULT_ON */
Kyle McMartin0cd5c3c2009-02-04 14:29:19 -0800373
Lu Baolu04618252020-01-02 08:18:02 +0800374#ifdef INTEL_IOMMU_SCALABLE_MODE_DEFAULT_ON
375int intel_iommu_sm = 1;
376#else
Sai Praneeth Prakhyacdd3a242019-05-24 16:40:16 -0700377int intel_iommu_sm;
Lu Baolu04618252020-01-02 08:18:02 +0800378#endif /* INTEL_IOMMU_SCALABLE_MODE_DEFAULT_ON */
379
Eugeni Dodonov8bc1f852011-11-23 16:42:14 -0200380int intel_iommu_enabled = 0;
381EXPORT_SYMBOL_GPL(intel_iommu_enabled);
382
David Woodhouse2d9e6672010-06-15 10:57:57 +0100383static int dmar_map_gfx = 1;
Keshavamurthy, Anil S7d3b03c2007-10-21 16:41:53 -0700384static int dmar_forcedac;
mark gross5e0d2a62008-03-04 15:22:08 -0800385static int intel_iommu_strict;
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100386static int intel_iommu_superpage = 1;
David Woodhouseae853dd2015-09-09 11:58:59 +0100387static int iommu_identity_mapping;
Lu Baolue5e04d02019-09-06 14:14:49 +0800388static int intel_no_bounce;
David Woodhousec83b2f22015-06-12 10:15:49 +0100389
David Woodhouseae853dd2015-09-09 11:58:59 +0100390#define IDENTMAP_GFX 2
391#define IDENTMAP_AZALIA 4
David Woodhousec83b2f22015-06-12 10:15:49 +0100392
David Woodhousec0771df2011-10-14 20:59:46 +0100393int intel_iommu_gfx_mapped;
394EXPORT_SYMBOL_GPL(intel_iommu_gfx_mapped);
395
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700396#define DUMMY_DEVICE_DOMAIN_INFO ((struct device_domain_info *)(-1))
Lu Baolu8af46c72019-05-25 13:41:32 +0800397#define DEFER_DEVICE_DOMAIN_INFO ((struct device_domain_info *)(-2))
Lu Baolue2726da2020-01-02 08:18:22 +0800398DEFINE_SPINLOCK(device_domain_lock);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700399static LIST_HEAD(device_domain_list);
400
Lu Baolue5e04d02019-09-06 14:14:49 +0800401#define device_needs_bounce(d) (!intel_no_bounce && dev_is_pci(d) && \
402 to_pci_dev(d)->untrusted)
403
Lu Baolu85319dc2018-07-14 15:46:58 +0800404/*
405 * Iterate over elements in device_domain_list and call the specified
Lu Baolu0bbeb012018-12-10 09:58:56 +0800406 * callback @fn against each element.
Lu Baolu85319dc2018-07-14 15:46:58 +0800407 */
408int for_each_device_domain(int (*fn)(struct device_domain_info *info,
409 void *data), void *data)
410{
411 int ret = 0;
Lu Baolu0bbeb012018-12-10 09:58:56 +0800412 unsigned long flags;
Lu Baolu85319dc2018-07-14 15:46:58 +0800413 struct device_domain_info *info;
414
Lu Baolu0bbeb012018-12-10 09:58:56 +0800415 spin_lock_irqsave(&device_domain_lock, flags);
Lu Baolu85319dc2018-07-14 15:46:58 +0800416 list_for_each_entry(info, &device_domain_list, global) {
417 ret = fn(info, data);
Lu Baolu0bbeb012018-12-10 09:58:56 +0800418 if (ret) {
419 spin_unlock_irqrestore(&device_domain_lock, flags);
Lu Baolu85319dc2018-07-14 15:46:58 +0800420 return ret;
Lu Baolu0bbeb012018-12-10 09:58:56 +0800421 }
Lu Baolu85319dc2018-07-14 15:46:58 +0800422 }
Lu Baolu0bbeb012018-12-10 09:58:56 +0800423 spin_unlock_irqrestore(&device_domain_lock, flags);
Lu Baolu85319dc2018-07-14 15:46:58 +0800424
425 return 0;
426}
427
Joerg Roedelb0119e82017-02-01 13:23:08 +0100428const struct iommu_ops intel_iommu_ops;
Joerg Roedela8bcbb0d2008-12-03 15:14:02 +0100429
Joerg Roedel4158c2e2015-06-12 10:14:02 +0200430static bool translation_pre_enabled(struct intel_iommu *iommu)
431{
432 return (iommu->flags & VTD_FLAG_TRANS_PRE_ENABLED);
433}
434
Joerg Roedel091d42e2015-06-12 11:56:10 +0200435static void clear_translation_pre_enabled(struct intel_iommu *iommu)
436{
437 iommu->flags &= ~VTD_FLAG_TRANS_PRE_ENABLED;
438}
439
Joerg Roedel4158c2e2015-06-12 10:14:02 +0200440static void init_translation_status(struct intel_iommu *iommu)
441{
442 u32 gsts;
443
444 gsts = readl(iommu->reg + DMAR_GSTS_REG);
445 if (gsts & DMA_GSTS_TES)
446 iommu->flags |= VTD_FLAG_TRANS_PRE_ENABLED;
447}
448
Joerg Roedel00a77de2015-03-26 13:43:08 +0100449/* Convert generic 'struct iommu_domain to private struct dmar_domain */
450static struct dmar_domain *to_dmar_domain(struct iommu_domain *dom)
451{
452 return container_of(dom, struct dmar_domain, domain);
453}
454
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700455static int __init intel_iommu_setup(char *str)
456{
457 if (!str)
458 return -EINVAL;
459 while (*str) {
Kyle McMartin0cd5c3c2009-02-04 14:29:19 -0800460 if (!strncmp(str, "on", 2)) {
461 dmar_disabled = 0;
Joerg Roedel9f10e5b2015-06-12 09:57:06 +0200462 pr_info("IOMMU enabled\n");
Kyle McMartin0cd5c3c2009-02-04 14:29:19 -0800463 } else if (!strncmp(str, "off", 3)) {
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700464 dmar_disabled = 1;
Lu Baolu89a60792018-10-23 15:45:01 +0800465 no_platform_optin = 1;
Joerg Roedel9f10e5b2015-06-12 09:57:06 +0200466 pr_info("IOMMU disabled\n");
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700467 } else if (!strncmp(str, "igfx_off", 8)) {
468 dmar_map_gfx = 0;
Joerg Roedel9f10e5b2015-06-12 09:57:06 +0200469 pr_info("Disable GFX device mapping\n");
Keshavamurthy, Anil S7d3b03c2007-10-21 16:41:53 -0700470 } else if (!strncmp(str, "forcedac", 8)) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +0200471 pr_info("Forcing DAC for PCI devices\n");
Keshavamurthy, Anil S7d3b03c2007-10-21 16:41:53 -0700472 dmar_forcedac = 1;
mark gross5e0d2a62008-03-04 15:22:08 -0800473 } else if (!strncmp(str, "strict", 6)) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +0200474 pr_info("Disable batched IOTLB flush\n");
mark gross5e0d2a62008-03-04 15:22:08 -0800475 intel_iommu_strict = 1;
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100476 } else if (!strncmp(str, "sp_off", 6)) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +0200477 pr_info("Disable supported super page\n");
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100478 intel_iommu_superpage = 0;
Lu Baolu8950dcd2019-01-24 10:31:32 +0800479 } else if (!strncmp(str, "sm_on", 5)) {
480 pr_info("Intel-IOMMU: scalable mode supported\n");
481 intel_iommu_sm = 1;
Shaohua Libfd20f12017-04-26 09:18:35 -0700482 } else if (!strncmp(str, "tboot_noforce", 13)) {
483 printk(KERN_INFO
484 "Intel-IOMMU: not forcing on after tboot. This could expose security risk for tboot\n");
485 intel_iommu_tboot_noforce = 1;
Lu Baolue5e04d02019-09-06 14:14:49 +0800486 } else if (!strncmp(str, "nobounce", 8)) {
487 pr_info("Intel-IOMMU: No bounce buffer. This could expose security risks of DMA attacks\n");
488 intel_no_bounce = 1;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700489 }
490
491 str += strcspn(str, ",");
492 while (*str == ',')
493 str++;
494 }
495 return 0;
496}
497__setup("intel_iommu=", intel_iommu_setup);
498
499static struct kmem_cache *iommu_domain_cache;
500static struct kmem_cache *iommu_devinfo_cache;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700501
Joerg Roedel9452d5b2015-07-21 10:00:56 +0200502static struct dmar_domain* get_iommu_domain(struct intel_iommu *iommu, u16 did)
503{
Joerg Roedel8bf47812015-07-21 10:41:21 +0200504 struct dmar_domain **domains;
505 int idx = did >> 8;
506
507 domains = iommu->domains[idx];
508 if (!domains)
509 return NULL;
510
511 return domains[did & 0xff];
Joerg Roedel9452d5b2015-07-21 10:00:56 +0200512}
513
514static void set_iommu_domain(struct intel_iommu *iommu, u16 did,
515 struct dmar_domain *domain)
516{
Joerg Roedel8bf47812015-07-21 10:41:21 +0200517 struct dmar_domain **domains;
518 int idx = did >> 8;
519
520 if (!iommu->domains[idx]) {
521 size_t size = 256 * sizeof(struct dmar_domain *);
522 iommu->domains[idx] = kzalloc(size, GFP_ATOMIC);
523 }
524
525 domains = iommu->domains[idx];
526 if (WARN_ON(!domains))
527 return;
528 else
529 domains[did & 0xff] = domain;
Joerg Roedel9452d5b2015-07-21 10:00:56 +0200530}
531
Lu Baolu9ddbfb42018-07-14 15:46:57 +0800532void *alloc_pgtable_page(int node)
Keshavamurthy, Anil Seb3fa7c2007-10-21 16:41:52 -0700533{
Suresh Siddha4c923d42009-10-02 11:01:24 -0700534 struct page *page;
535 void *vaddr = NULL;
Keshavamurthy, Anil Seb3fa7c2007-10-21 16:41:52 -0700536
Suresh Siddha4c923d42009-10-02 11:01:24 -0700537 page = alloc_pages_node(node, GFP_ATOMIC | __GFP_ZERO, 0);
538 if (page)
539 vaddr = page_address(page);
Keshavamurthy, Anil Seb3fa7c2007-10-21 16:41:52 -0700540 return vaddr;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700541}
542
Lu Baolu9ddbfb42018-07-14 15:46:57 +0800543void free_pgtable_page(void *vaddr)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700544{
545 free_page((unsigned long)vaddr);
546}
547
548static inline void *alloc_domain_mem(void)
549{
KOSAKI Motohiro354bb652009-11-17 16:21:09 +0900550 return kmem_cache_alloc(iommu_domain_cache, GFP_ATOMIC);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700551}
552
Kay, Allen M38717942008-09-09 18:37:29 +0300553static void free_domain_mem(void *vaddr)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700554{
555 kmem_cache_free(iommu_domain_cache, vaddr);
556}
557
558static inline void * alloc_devinfo_mem(void)
559{
KOSAKI Motohiro354bb652009-11-17 16:21:09 +0900560 return kmem_cache_alloc(iommu_devinfo_cache, GFP_ATOMIC);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700561}
562
563static inline void free_devinfo_mem(void *vaddr)
564{
565 kmem_cache_free(iommu_devinfo_cache, vaddr);
566}
567
Joerg Roedel28ccce02015-07-21 14:45:31 +0200568static inline int domain_type_is_si(struct dmar_domain *domain)
569{
570 return domain->flags & DOMAIN_FLAG_STATIC_IDENTITY;
571}
572
Lu Baoluddf09b62020-01-02 08:18:17 +0800573static inline bool domain_use_first_level(struct dmar_domain *domain)
574{
575 return domain->flags & DOMAIN_FLAG_USE_FIRST_LEVEL;
576}
577
Jiang Liu162d1b12014-07-11 14:19:35 +0800578static inline int domain_pfn_supported(struct dmar_domain *domain,
579 unsigned long pfn)
580{
581 int addr_width = agaw_to_width(domain->agaw) - VTD_PAGE_SHIFT;
582
583 return !(addr_width < BITS_PER_LONG && pfn >> addr_width);
584}
585
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -0700586static int __iommu_calculate_agaw(struct intel_iommu *iommu, int max_gaw)
Weidong Han1b573682008-12-08 15:34:06 +0800587{
588 unsigned long sagaw;
589 int agaw = -1;
590
591 sagaw = cap_sagaw(iommu->cap);
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -0700592 for (agaw = width_to_agaw(max_gaw);
Weidong Han1b573682008-12-08 15:34:06 +0800593 agaw >= 0; agaw--) {
594 if (test_bit(agaw, &sagaw))
595 break;
596 }
597
598 return agaw;
599}
600
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -0700601/*
602 * Calculate max SAGAW for each iommu.
603 */
604int iommu_calculate_max_sagaw(struct intel_iommu *iommu)
605{
606 return __iommu_calculate_agaw(iommu, MAX_AGAW_WIDTH);
607}
608
609/*
610 * calculate agaw for each iommu.
611 * "SAGAW" may be different across iommus, use a default agaw, and
612 * get a supported less agaw for iommus that don't support the default agaw.
613 */
614int iommu_calculate_agaw(struct intel_iommu *iommu)
615{
616 return __iommu_calculate_agaw(iommu, DEFAULT_DOMAIN_ADDRESS_WIDTH);
617}
618
Fenghua Yu2c2e2c32009-06-19 13:47:29 -0700619/* This functionin only returns single iommu in a domain */
Lu Baolu9ddbfb42018-07-14 15:46:57 +0800620struct intel_iommu *domain_get_iommu(struct dmar_domain *domain)
Weidong Han8c11e792008-12-08 15:29:22 +0800621{
622 int iommu_id;
623
Fenghua Yu2c2e2c32009-06-19 13:47:29 -0700624 /* si_domain and vm domain should not get here. */
Lu Baolufa954e62019-05-25 13:41:28 +0800625 if (WARN_ON(domain->domain.type != IOMMU_DOMAIN_DMA))
626 return NULL;
627
Joerg Roedel29a27712015-07-21 17:17:12 +0200628 for_each_domain_iommu(iommu_id, domain)
629 break;
630
Weidong Han8c11e792008-12-08 15:29:22 +0800631 if (iommu_id < 0 || iommu_id >= g_num_of_iommus)
632 return NULL;
633
634 return g_iommus[iommu_id];
635}
636
Weidong Han8e6040972008-12-08 15:49:06 +0800637static void domain_update_iommu_coherency(struct dmar_domain *domain)
638{
David Woodhoused0501962014-03-11 17:10:29 -0700639 struct dmar_drhd_unit *drhd;
640 struct intel_iommu *iommu;
Quentin Lambert2f119c72015-02-06 10:59:53 +0100641 bool found = false;
642 int i;
Weidong Han8e6040972008-12-08 15:49:06 +0800643
David Woodhoused0501962014-03-11 17:10:29 -0700644 domain->iommu_coherency = 1;
Weidong Han8e6040972008-12-08 15:49:06 +0800645
Joerg Roedel29a27712015-07-21 17:17:12 +0200646 for_each_domain_iommu(i, domain) {
Quentin Lambert2f119c72015-02-06 10:59:53 +0100647 found = true;
Weidong Han8e6040972008-12-08 15:49:06 +0800648 if (!ecap_coherent(g_iommus[i]->ecap)) {
649 domain->iommu_coherency = 0;
650 break;
651 }
Weidong Han8e6040972008-12-08 15:49:06 +0800652 }
David Woodhoused0501962014-03-11 17:10:29 -0700653 if (found)
654 return;
655
656 /* No hardware attached; use lowest common denominator */
657 rcu_read_lock();
658 for_each_active_iommu(iommu, drhd) {
659 if (!ecap_coherent(iommu->ecap)) {
660 domain->iommu_coherency = 0;
661 break;
662 }
663 }
664 rcu_read_unlock();
Weidong Han8e6040972008-12-08 15:49:06 +0800665}
666
Jiang Liu161f6932014-07-11 14:19:37 +0800667static int domain_update_iommu_snooping(struct intel_iommu *skip)
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100668{
Allen Kay8140a952011-10-14 12:32:17 -0700669 struct dmar_drhd_unit *drhd;
Jiang Liu161f6932014-07-11 14:19:37 +0800670 struct intel_iommu *iommu;
671 int ret = 1;
672
673 rcu_read_lock();
674 for_each_active_iommu(iommu, drhd) {
675 if (iommu != skip) {
676 if (!ecap_sc_support(iommu->ecap)) {
677 ret = 0;
678 break;
679 }
680 }
681 }
682 rcu_read_unlock();
683
684 return ret;
685}
686
Lu Baolu64229e82020-01-02 08:18:20 +0800687static int domain_update_iommu_superpage(struct dmar_domain *domain,
688 struct intel_iommu *skip)
Jiang Liu161f6932014-07-11 14:19:37 +0800689{
690 struct dmar_drhd_unit *drhd;
691 struct intel_iommu *iommu;
Lu Baolu64229e82020-01-02 08:18:20 +0800692 int mask = 0x3;
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100693
694 if (!intel_iommu_superpage) {
Jiang Liu161f6932014-07-11 14:19:37 +0800695 return 0;
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100696 }
697
Allen Kay8140a952011-10-14 12:32:17 -0700698 /* set iommu_superpage to the smallest common denominator */
Jiang Liu0e242612014-02-19 14:07:34 +0800699 rcu_read_lock();
Allen Kay8140a952011-10-14 12:32:17 -0700700 for_each_active_iommu(iommu, drhd) {
Jiang Liu161f6932014-07-11 14:19:37 +0800701 if (iommu != skip) {
Lu Baolu64229e82020-01-02 08:18:20 +0800702 if (domain && domain_use_first_level(domain)) {
703 if (!cap_fl1gp_support(iommu->cap))
704 mask = 0x1;
705 } else {
706 mask &= cap_super_page_val(iommu->cap);
707 }
708
Jiang Liu161f6932014-07-11 14:19:37 +0800709 if (!mask)
710 break;
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100711 }
712 }
Jiang Liu0e242612014-02-19 14:07:34 +0800713 rcu_read_unlock();
714
Jiang Liu161f6932014-07-11 14:19:37 +0800715 return fls(mask);
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100716}
717
Sheng Yang58c610b2009-03-18 15:33:05 +0800718/* Some capabilities may be different across iommus */
719static void domain_update_iommu_cap(struct dmar_domain *domain)
720{
721 domain_update_iommu_coherency(domain);
Jiang Liu161f6932014-07-11 14:19:37 +0800722 domain->iommu_snooping = domain_update_iommu_snooping(NULL);
Lu Baolu64229e82020-01-02 08:18:20 +0800723 domain->iommu_superpage = domain_update_iommu_superpage(domain, NULL);
Sheng Yang58c610b2009-03-18 15:33:05 +0800724}
725
Sohil Mehta26b86092018-09-11 17:11:36 -0700726struct context_entry *iommu_context_addr(struct intel_iommu *iommu, u8 bus,
727 u8 devfn, int alloc)
David Woodhouse03ecc322015-02-13 14:35:21 +0000728{
729 struct root_entry *root = &iommu->root_entry[bus];
730 struct context_entry *context;
731 u64 *entry;
732
Joerg Roedel4df4eab2015-08-25 10:54:28 +0200733 entry = &root->lo;
Lu Baolu765b6a92018-12-10 09:58:55 +0800734 if (sm_supported(iommu)) {
David Woodhouse03ecc322015-02-13 14:35:21 +0000735 if (devfn >= 0x80) {
736 devfn -= 0x80;
737 entry = &root->hi;
738 }
739 devfn *= 2;
740 }
David Woodhouse03ecc322015-02-13 14:35:21 +0000741 if (*entry & 1)
742 context = phys_to_virt(*entry & VTD_PAGE_MASK);
743 else {
744 unsigned long phy_addr;
745 if (!alloc)
746 return NULL;
747
748 context = alloc_pgtable_page(iommu->node);
749 if (!context)
750 return NULL;
751
752 __iommu_flush_cache(iommu, (void *)context, CONTEXT_SIZE);
753 phy_addr = virt_to_phys((void *)context);
754 *entry = phy_addr | 1;
755 __iommu_flush_cache(iommu, entry, sizeof(*entry));
756 }
757 return &context[devfn];
758}
759
David Woodhouse4ed6a542015-05-11 14:59:20 +0100760static int iommu_dummy(struct device *dev)
761{
762 return dev->archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO;
763}
764
Joerg Roedel1d46159782020-02-17 17:12:37 +0100765static bool attach_deferred(struct device *dev)
766{
767 return dev->archdata.iommu == DEFER_DEVICE_DOMAIN_INFO;
768}
769
Eric Augerb9a7f982019-06-03 08:53:32 +0200770/**
771 * is_downstream_to_pci_bridge - test if a device belongs to the PCI
772 * sub-hierarchy of a candidate PCI-PCI bridge
773 * @dev: candidate PCI device belonging to @bridge PCI sub-hierarchy
774 * @bridge: the candidate PCI-PCI bridge
775 *
776 * Return: true if @dev belongs to @bridge PCI sub-hierarchy, else false.
777 */
778static bool
779is_downstream_to_pci_bridge(struct device *dev, struct device *bridge)
780{
781 struct pci_dev *pdev, *pbridge;
782
783 if (!dev_is_pci(dev) || !dev_is_pci(bridge))
784 return false;
785
786 pdev = to_pci_dev(dev);
787 pbridge = to_pci_dev(bridge);
788
789 if (pbridge->subordinate &&
790 pbridge->subordinate->number <= pdev->bus->number &&
791 pbridge->subordinate->busn_res.end >= pdev->bus->number)
792 return true;
793
794 return false;
795}
796
David Woodhouse156baca2014-03-09 14:00:57 -0700797static struct intel_iommu *device_to_iommu(struct device *dev, u8 *bus, u8 *devfn)
Weidong Hanc7151a82008-12-08 22:51:37 +0800798{
799 struct dmar_drhd_unit *drhd = NULL;
Jiang Liub683b232014-02-19 14:07:32 +0800800 struct intel_iommu *iommu;
David Woodhouse156baca2014-03-09 14:00:57 -0700801 struct device *tmp;
Eric Augerb9a7f982019-06-03 08:53:32 +0200802 struct pci_dev *pdev = NULL;
Yijing Wangaa4d0662014-05-26 20:14:06 +0800803 u16 segment = 0;
Weidong Hanc7151a82008-12-08 22:51:37 +0800804 int i;
805
David Woodhouse4ed6a542015-05-11 14:59:20 +0100806 if (iommu_dummy(dev))
807 return NULL;
808
David Woodhouse156baca2014-03-09 14:00:57 -0700809 if (dev_is_pci(dev)) {
Ashok Raj1c387182016-10-21 15:32:05 -0700810 struct pci_dev *pf_pdev;
811
Jon Derricke3560ee2020-01-21 06:37:49 -0700812 pdev = pci_real_dma_dev(to_pci_dev(dev));
Jon Derrick5823e332017-08-30 15:05:59 -0600813
Ashok Raj1c387182016-10-21 15:32:05 -0700814 /* VFs aren't listed in scope tables; we need to look up
815 * the PF instead to find the IOMMU. */
816 pf_pdev = pci_physfn(pdev);
817 dev = &pf_pdev->dev;
David Woodhouse156baca2014-03-09 14:00:57 -0700818 segment = pci_domain_nr(pdev->bus);
Rafael J. Wysockica5b74d2015-03-16 23:49:08 +0100819 } else if (has_acpi_companion(dev))
David Woodhouse156baca2014-03-09 14:00:57 -0700820 dev = &ACPI_COMPANION(dev)->dev;
821
Jiang Liu0e242612014-02-19 14:07:34 +0800822 rcu_read_lock();
Jiang Liub683b232014-02-19 14:07:32 +0800823 for_each_active_iommu(iommu, drhd) {
David Woodhouse156baca2014-03-09 14:00:57 -0700824 if (pdev && segment != drhd->segment)
David Woodhouse276dbf992009-04-04 01:45:37 +0100825 continue;
Weidong Hanc7151a82008-12-08 22:51:37 +0800826
Jiang Liub683b232014-02-19 14:07:32 +0800827 for_each_active_dev_scope(drhd->devices,
David Woodhouse156baca2014-03-09 14:00:57 -0700828 drhd->devices_cnt, i, tmp) {
829 if (tmp == dev) {
Ashok Raj1c387182016-10-21 15:32:05 -0700830 /* For a VF use its original BDF# not that of the PF
831 * which we used for the IOMMU lookup. Strictly speaking
832 * we could do this for all PCI devices; we only need to
833 * get the BDF# from the scope table for ACPI matches. */
Koos Vriezen5003ae12017-03-01 21:02:50 +0100834 if (pdev && pdev->is_virtfn)
Ashok Raj1c387182016-10-21 15:32:05 -0700835 goto got_pdev;
836
David Woodhouse156baca2014-03-09 14:00:57 -0700837 *bus = drhd->devices[i].bus;
838 *devfn = drhd->devices[i].devfn;
839 goto out;
840 }
841
Eric Augerb9a7f982019-06-03 08:53:32 +0200842 if (is_downstream_to_pci_bridge(dev, tmp))
David Woodhouse156baca2014-03-09 14:00:57 -0700843 goto got_pdev;
David Woodhouse924b6232009-04-04 00:39:25 +0100844 }
Weidong Hanc7151a82008-12-08 22:51:37 +0800845
David Woodhouse156baca2014-03-09 14:00:57 -0700846 if (pdev && drhd->include_all) {
847 got_pdev:
848 *bus = pdev->bus->number;
849 *devfn = pdev->devfn;
Jiang Liub683b232014-02-19 14:07:32 +0800850 goto out;
David Woodhouse156baca2014-03-09 14:00:57 -0700851 }
Weidong Hanc7151a82008-12-08 22:51:37 +0800852 }
Jiang Liub683b232014-02-19 14:07:32 +0800853 iommu = NULL;
David Woodhouse156baca2014-03-09 14:00:57 -0700854 out:
Jiang Liu0e242612014-02-19 14:07:34 +0800855 rcu_read_unlock();
Weidong Hanc7151a82008-12-08 22:51:37 +0800856
Jiang Liub683b232014-02-19 14:07:32 +0800857 return iommu;
Weidong Hanc7151a82008-12-08 22:51:37 +0800858}
859
Weidong Han5331fe62008-12-08 23:00:00 +0800860static void domain_flush_cache(struct dmar_domain *domain,
861 void *addr, int size)
862{
863 if (!domain->iommu_coherency)
864 clflush_cache_range(addr, size);
865}
866
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700867static int device_context_mapped(struct intel_iommu *iommu, u8 bus, u8 devfn)
868{
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700869 struct context_entry *context;
David Woodhouse03ecc322015-02-13 14:35:21 +0000870 int ret = 0;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700871 unsigned long flags;
872
873 spin_lock_irqsave(&iommu->lock, flags);
David Woodhouse03ecc322015-02-13 14:35:21 +0000874 context = iommu_context_addr(iommu, bus, devfn, 0);
875 if (context)
876 ret = context_present(context);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700877 spin_unlock_irqrestore(&iommu->lock, flags);
878 return ret;
879}
880
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700881static void free_context_table(struct intel_iommu *iommu)
882{
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700883 int i;
884 unsigned long flags;
885 struct context_entry *context;
886
887 spin_lock_irqsave(&iommu->lock, flags);
888 if (!iommu->root_entry) {
889 goto out;
890 }
891 for (i = 0; i < ROOT_ENTRY_NR; i++) {
David Woodhouse03ecc322015-02-13 14:35:21 +0000892 context = iommu_context_addr(iommu, i, 0, 0);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700893 if (context)
894 free_pgtable_page(context);
David Woodhouse03ecc322015-02-13 14:35:21 +0000895
Lu Baolu765b6a92018-12-10 09:58:55 +0800896 if (!sm_supported(iommu))
David Woodhouse03ecc322015-02-13 14:35:21 +0000897 continue;
898
899 context = iommu_context_addr(iommu, i, 0x80, 0);
900 if (context)
901 free_pgtable_page(context);
902
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700903 }
904 free_pgtable_page(iommu->root_entry);
905 iommu->root_entry = NULL;
906out:
907 spin_unlock_irqrestore(&iommu->lock, flags);
908}
909
David Woodhouseb026fd22009-06-28 10:37:25 +0100910static struct dma_pte *pfn_to_dma_pte(struct dmar_domain *domain,
David Woodhouse5cf0a762014-03-19 16:07:49 +0000911 unsigned long pfn, int *target_level)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700912{
Bjorn Helgaase083ea5b2019-02-08 16:06:08 -0600913 struct dma_pte *parent, *pte;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700914 int level = agaw_to_level(domain->agaw);
Allen Kay4399c8b2011-10-14 12:32:46 -0700915 int offset;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700916
917 BUG_ON(!domain->pgd);
Julian Stecklinaf9423602013-10-09 10:03:52 +0200918
Jiang Liu162d1b12014-07-11 14:19:35 +0800919 if (!domain_pfn_supported(domain, pfn))
Julian Stecklinaf9423602013-10-09 10:03:52 +0200920 /* Address beyond IOMMU's addressing capabilities. */
921 return NULL;
922
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700923 parent = domain->pgd;
924
David Woodhouse5cf0a762014-03-19 16:07:49 +0000925 while (1) {
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700926 void *tmp_page;
927
David Woodhouseb026fd22009-06-28 10:37:25 +0100928 offset = pfn_level_offset(pfn, level);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700929 pte = &parent[offset];
David Woodhouse5cf0a762014-03-19 16:07:49 +0000930 if (!*target_level && (dma_pte_superpage(pte) || !dma_pte_present(pte)))
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100931 break;
David Woodhouse5cf0a762014-03-19 16:07:49 +0000932 if (level == *target_level)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700933 break;
934
Mark McLoughlin19c239c2008-11-21 16:56:53 +0000935 if (!dma_pte_present(pte)) {
David Woodhousec85994e2009-07-01 19:21:24 +0100936 uint64_t pteval;
937
Suresh Siddha4c923d42009-10-02 11:01:24 -0700938 tmp_page = alloc_pgtable_page(domain->nid);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700939
David Woodhouse206a73c2009-07-01 19:30:28 +0100940 if (!tmp_page)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700941 return NULL;
David Woodhouse206a73c2009-07-01 19:30:28 +0100942
David Woodhousec85994e2009-07-01 19:21:24 +0100943 domain_flush_cache(domain, tmp_page, VTD_PAGE_SIZE);
Benjamin LaHaise64de5af2009-09-16 21:05:55 -0400944 pteval = ((uint64_t)virt_to_dma_pfn(tmp_page) << VTD_PAGE_SHIFT) | DMA_PTE_READ | DMA_PTE_WRITE;
Lu Baoluddf09b62020-01-02 08:18:17 +0800945 if (domain_use_first_level(domain))
946 pteval |= DMA_FL_PTE_XD;
Yijing Wangeffad4b2014-05-26 20:13:47 +0800947 if (cmpxchg64(&pte->val, 0ULL, pteval))
David Woodhousec85994e2009-07-01 19:21:24 +0100948 /* Someone else set it while we were thinking; use theirs. */
949 free_pgtable_page(tmp_page);
Yijing Wangeffad4b2014-05-26 20:13:47 +0800950 else
David Woodhousec85994e2009-07-01 19:21:24 +0100951 domain_flush_cache(domain, pte, sizeof(*pte));
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700952 }
David Woodhouse5cf0a762014-03-19 16:07:49 +0000953 if (level == 1)
954 break;
955
Mark McLoughlin19c239c2008-11-21 16:56:53 +0000956 parent = phys_to_virt(dma_pte_addr(pte));
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700957 level--;
958 }
959
David Woodhouse5cf0a762014-03-19 16:07:49 +0000960 if (!*target_level)
961 *target_level = level;
962
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700963 return pte;
964}
965
966/* return address's pte at specific level */
David Woodhouse90dcfb52009-06-27 17:14:59 +0100967static struct dma_pte *dma_pfn_level_pte(struct dmar_domain *domain,
968 unsigned long pfn,
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100969 int level, int *large_page)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700970{
Bjorn Helgaase083ea5b2019-02-08 16:06:08 -0600971 struct dma_pte *parent, *pte;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700972 int total = agaw_to_level(domain->agaw);
973 int offset;
974
975 parent = domain->pgd;
976 while (level <= total) {
David Woodhouse90dcfb52009-06-27 17:14:59 +0100977 offset = pfn_level_offset(pfn, total);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700978 pte = &parent[offset];
979 if (level == total)
980 return pte;
981
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100982 if (!dma_pte_present(pte)) {
983 *large_page = total;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700984 break;
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100985 }
986
Yijing Wange16922a2014-05-20 20:37:51 +0800987 if (dma_pte_superpage(pte)) {
Youquan Song6dd9a7c2011-05-25 19:13:49 +0100988 *large_page = total;
989 return pte;
990 }
991
Mark McLoughlin19c239c2008-11-21 16:56:53 +0000992 parent = phys_to_virt(dma_pte_addr(pte));
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700993 total--;
994 }
995 return NULL;
996}
997
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -0700998/* clear last level pte, a tlb flush should be followed */
David Woodhouse5cf0a762014-03-19 16:07:49 +0000999static void dma_pte_clear_range(struct dmar_domain *domain,
David Woodhouse595badf52009-06-27 22:09:11 +01001000 unsigned long start_pfn,
1001 unsigned long last_pfn)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001002{
Bjorn Helgaase083ea5b2019-02-08 16:06:08 -06001003 unsigned int large_page;
David Woodhouse310a5ab2009-06-28 18:52:20 +01001004 struct dma_pte *first_pte, *pte;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001005
Jiang Liu162d1b12014-07-11 14:19:35 +08001006 BUG_ON(!domain_pfn_supported(domain, start_pfn));
1007 BUG_ON(!domain_pfn_supported(domain, last_pfn));
David Woodhouse59c36282009-09-19 07:36:28 -07001008 BUG_ON(start_pfn > last_pfn);
David Woodhouse66eae842009-06-27 19:00:32 +01001009
David Woodhouse04b18e62009-06-27 19:15:01 +01001010 /* we don't need lock here; nobody else touches the iova range */
David Woodhouse59c36282009-09-19 07:36:28 -07001011 do {
Youquan Song6dd9a7c2011-05-25 19:13:49 +01001012 large_page = 1;
1013 first_pte = pte = dma_pfn_level_pte(domain, start_pfn, 1, &large_page);
David Woodhouse310a5ab2009-06-28 18:52:20 +01001014 if (!pte) {
Youquan Song6dd9a7c2011-05-25 19:13:49 +01001015 start_pfn = align_to_level(start_pfn + 1, large_page + 1);
David Woodhouse310a5ab2009-06-28 18:52:20 +01001016 continue;
1017 }
Youquan Song6dd9a7c2011-05-25 19:13:49 +01001018 do {
David Woodhouse310a5ab2009-06-28 18:52:20 +01001019 dma_clear_pte(pte);
Youquan Song6dd9a7c2011-05-25 19:13:49 +01001020 start_pfn += lvl_to_nr_pages(large_page);
David Woodhouse310a5ab2009-06-28 18:52:20 +01001021 pte++;
David Woodhouse75e6bf92009-07-02 11:21:16 +01001022 } while (start_pfn <= last_pfn && !first_pte_in_page(pte));
1023
David Woodhouse310a5ab2009-06-28 18:52:20 +01001024 domain_flush_cache(domain, first_pte,
1025 (void *)pte - (void *)first_pte);
David Woodhouse59c36282009-09-19 07:36:28 -07001026
1027 } while (start_pfn && start_pfn <= last_pfn);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001028}
1029
Alex Williamson3269ee02013-06-15 10:27:19 -06001030static void dma_pte_free_level(struct dmar_domain *domain, int level,
David Dillowbc24c572017-06-28 19:42:23 -07001031 int retain_level, struct dma_pte *pte,
1032 unsigned long pfn, unsigned long start_pfn,
1033 unsigned long last_pfn)
Alex Williamson3269ee02013-06-15 10:27:19 -06001034{
1035 pfn = max(start_pfn, pfn);
1036 pte = &pte[pfn_level_offset(pfn, level)];
1037
1038 do {
1039 unsigned long level_pfn;
1040 struct dma_pte *level_pte;
1041
1042 if (!dma_pte_present(pte) || dma_pte_superpage(pte))
1043 goto next;
1044
David Dillowf7116e12017-01-30 19:11:11 -08001045 level_pfn = pfn & level_mask(level);
Alex Williamson3269ee02013-06-15 10:27:19 -06001046 level_pte = phys_to_virt(dma_pte_addr(pte));
1047
David Dillowbc24c572017-06-28 19:42:23 -07001048 if (level > 2) {
1049 dma_pte_free_level(domain, level - 1, retain_level,
1050 level_pte, level_pfn, start_pfn,
1051 last_pfn);
1052 }
Alex Williamson3269ee02013-06-15 10:27:19 -06001053
David Dillowbc24c572017-06-28 19:42:23 -07001054 /*
1055 * Free the page table if we're below the level we want to
1056 * retain and the range covers the entire table.
1057 */
1058 if (level < retain_level && !(start_pfn > level_pfn ||
Alex Williamson08336fd2014-01-21 15:48:18 -08001059 last_pfn < level_pfn + level_size(level) - 1)) {
Alex Williamson3269ee02013-06-15 10:27:19 -06001060 dma_clear_pte(pte);
1061 domain_flush_cache(domain, pte, sizeof(*pte));
1062 free_pgtable_page(level_pte);
1063 }
1064next:
1065 pfn += level_size(level);
1066 } while (!first_pte_in_page(++pte) && pfn <= last_pfn);
1067}
1068
David Dillowbc24c572017-06-28 19:42:23 -07001069/*
1070 * clear last level (leaf) ptes and free page table pages below the
1071 * level we wish to keep intact.
1072 */
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001073static void dma_pte_free_pagetable(struct dmar_domain *domain,
David Woodhoused794dc92009-06-28 00:27:49 +01001074 unsigned long start_pfn,
David Dillowbc24c572017-06-28 19:42:23 -07001075 unsigned long last_pfn,
1076 int retain_level)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001077{
Jiang Liu162d1b12014-07-11 14:19:35 +08001078 BUG_ON(!domain_pfn_supported(domain, start_pfn));
1079 BUG_ON(!domain_pfn_supported(domain, last_pfn));
David Woodhouse59c36282009-09-19 07:36:28 -07001080 BUG_ON(start_pfn > last_pfn);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001081
Jiang Liud41a4ad2014-07-11 14:19:34 +08001082 dma_pte_clear_range(domain, start_pfn, last_pfn);
1083
David Woodhousef3a0a522009-06-30 03:40:07 +01001084 /* We don't need lock here; nobody else touches the iova range */
David Dillowbc24c572017-06-28 19:42:23 -07001085 dma_pte_free_level(domain, agaw_to_level(domain->agaw), retain_level,
Alex Williamson3269ee02013-06-15 10:27:19 -06001086 domain->pgd, 0, start_pfn, last_pfn);
David Woodhouse6660c632009-06-27 22:41:00 +01001087
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001088 /* free pgd */
David Woodhoused794dc92009-06-28 00:27:49 +01001089 if (start_pfn == 0 && last_pfn == DOMAIN_MAX_PFN(domain->gaw)) {
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001090 free_pgtable_page(domain->pgd);
1091 domain->pgd = NULL;
1092 }
1093}
1094
David Woodhouseea8ea462014-03-05 17:09:32 +00001095/* When a page at a given level is being unlinked from its parent, we don't
1096 need to *modify* it at all. All we need to do is make a list of all the
1097 pages which can be freed just as soon as we've flushed the IOTLB and we
1098 know the hardware page-walk will no longer touch them.
1099 The 'pte' argument is the *parent* PTE, pointing to the page that is to
1100 be freed. */
1101static struct page *dma_pte_list_pagetables(struct dmar_domain *domain,
1102 int level, struct dma_pte *pte,
1103 struct page *freelist)
1104{
1105 struct page *pg;
1106
1107 pg = pfn_to_page(dma_pte_addr(pte) >> PAGE_SHIFT);
1108 pg->freelist = freelist;
1109 freelist = pg;
1110
1111 if (level == 1)
1112 return freelist;
1113
Jiang Liuadeb2592014-04-09 10:20:39 +08001114 pte = page_address(pg);
1115 do {
David Woodhouseea8ea462014-03-05 17:09:32 +00001116 if (dma_pte_present(pte) && !dma_pte_superpage(pte))
1117 freelist = dma_pte_list_pagetables(domain, level - 1,
1118 pte, freelist);
Jiang Liuadeb2592014-04-09 10:20:39 +08001119 pte++;
1120 } while (!first_pte_in_page(pte));
David Woodhouseea8ea462014-03-05 17:09:32 +00001121
1122 return freelist;
1123}
1124
1125static struct page *dma_pte_clear_level(struct dmar_domain *domain, int level,
1126 struct dma_pte *pte, unsigned long pfn,
1127 unsigned long start_pfn,
1128 unsigned long last_pfn,
1129 struct page *freelist)
1130{
1131 struct dma_pte *first_pte = NULL, *last_pte = NULL;
1132
1133 pfn = max(start_pfn, pfn);
1134 pte = &pte[pfn_level_offset(pfn, level)];
1135
1136 do {
1137 unsigned long level_pfn;
1138
1139 if (!dma_pte_present(pte))
1140 goto next;
1141
1142 level_pfn = pfn & level_mask(level);
1143
1144 /* If range covers entire pagetable, free it */
1145 if (start_pfn <= level_pfn &&
1146 last_pfn >= level_pfn + level_size(level) - 1) {
1147 /* These suborbinate page tables are going away entirely. Don't
1148 bother to clear them; we're just going to *free* them. */
1149 if (level > 1 && !dma_pte_superpage(pte))
1150 freelist = dma_pte_list_pagetables(domain, level - 1, pte, freelist);
1151
1152 dma_clear_pte(pte);
1153 if (!first_pte)
1154 first_pte = pte;
1155 last_pte = pte;
1156 } else if (level > 1) {
1157 /* Recurse down into a level that isn't *entirely* obsolete */
1158 freelist = dma_pte_clear_level(domain, level - 1,
1159 phys_to_virt(dma_pte_addr(pte)),
1160 level_pfn, start_pfn, last_pfn,
1161 freelist);
1162 }
1163next:
1164 pfn += level_size(level);
1165 } while (!first_pte_in_page(++pte) && pfn <= last_pfn);
1166
1167 if (first_pte)
1168 domain_flush_cache(domain, first_pte,
1169 (void *)++last_pte - (void *)first_pte);
1170
1171 return freelist;
1172}
1173
1174/* We can't just free the pages because the IOMMU may still be walking
1175 the page tables, and may have cached the intermediate levels. The
1176 pages can only be freed after the IOTLB flush has been done. */
Joerg Roedelb6904202015-08-13 11:32:18 +02001177static struct page *domain_unmap(struct dmar_domain *domain,
1178 unsigned long start_pfn,
1179 unsigned long last_pfn)
David Woodhouseea8ea462014-03-05 17:09:32 +00001180{
Bjorn Helgaase083ea5b2019-02-08 16:06:08 -06001181 struct page *freelist;
David Woodhouseea8ea462014-03-05 17:09:32 +00001182
Jiang Liu162d1b12014-07-11 14:19:35 +08001183 BUG_ON(!domain_pfn_supported(domain, start_pfn));
1184 BUG_ON(!domain_pfn_supported(domain, last_pfn));
David Woodhouseea8ea462014-03-05 17:09:32 +00001185 BUG_ON(start_pfn > last_pfn);
1186
1187 /* we don't need lock here; nobody else touches the iova range */
1188 freelist = dma_pte_clear_level(domain, agaw_to_level(domain->agaw),
1189 domain->pgd, 0, start_pfn, last_pfn, NULL);
1190
1191 /* free pgd */
1192 if (start_pfn == 0 && last_pfn == DOMAIN_MAX_PFN(domain->gaw)) {
1193 struct page *pgd_page = virt_to_page(domain->pgd);
1194 pgd_page->freelist = freelist;
1195 freelist = pgd_page;
1196
1197 domain->pgd = NULL;
1198 }
1199
1200 return freelist;
1201}
1202
Joerg Roedelb6904202015-08-13 11:32:18 +02001203static void dma_free_pagelist(struct page *freelist)
David Woodhouseea8ea462014-03-05 17:09:32 +00001204{
1205 struct page *pg;
1206
1207 while ((pg = freelist)) {
1208 freelist = pg->freelist;
1209 free_pgtable_page(page_address(pg));
1210 }
1211}
1212
Joerg Roedel13cf0172017-08-11 11:40:10 +02001213static void iova_entry_free(unsigned long data)
1214{
1215 struct page *freelist = (struct page *)data;
1216
1217 dma_free_pagelist(freelist);
1218}
1219
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001220/* iommu handling */
1221static int iommu_alloc_root_entry(struct intel_iommu *iommu)
1222{
1223 struct root_entry *root;
1224 unsigned long flags;
1225
Suresh Siddha4c923d42009-10-02 11:01:24 -07001226 root = (struct root_entry *)alloc_pgtable_page(iommu->node);
Jiang Liuffebeb42014-11-09 22:48:02 +08001227 if (!root) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02001228 pr_err("Allocating root entry for %s failed\n",
Jiang Liuffebeb42014-11-09 22:48:02 +08001229 iommu->name);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001230 return -ENOMEM;
Jiang Liuffebeb42014-11-09 22:48:02 +08001231 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001232
Fenghua Yu5b6985c2008-10-16 18:02:32 -07001233 __iommu_flush_cache(iommu, root, ROOT_SIZE);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001234
1235 spin_lock_irqsave(&iommu->lock, flags);
1236 iommu->root_entry = root;
1237 spin_unlock_irqrestore(&iommu->lock, flags);
1238
1239 return 0;
1240}
1241
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001242static void iommu_set_root_entry(struct intel_iommu *iommu)
1243{
David Woodhouse03ecc322015-02-13 14:35:21 +00001244 u64 addr;
David Woodhousec416daa2009-05-10 20:30:58 +01001245 u32 sts;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001246 unsigned long flag;
1247
David Woodhouse03ecc322015-02-13 14:35:21 +00001248 addr = virt_to_phys(iommu->root_entry);
Lu Baolu7373a8c2018-12-10 09:59:03 +08001249 if (sm_supported(iommu))
1250 addr |= DMA_RTADDR_SMT;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001251
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001252 raw_spin_lock_irqsave(&iommu->register_lock, flag);
David Woodhouse03ecc322015-02-13 14:35:21 +00001253 dmar_writeq(iommu->reg + DMAR_RTADDR_REG, addr);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001254
David Woodhousec416daa2009-05-10 20:30:58 +01001255 writel(iommu->gcmd | DMA_GCMD_SRTP, iommu->reg + DMAR_GCMD_REG);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001256
1257 /* Make sure hardware complete it */
1258 IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
David Woodhousec416daa2009-05-10 20:30:58 +01001259 readl, (sts & DMA_GSTS_RTPS), sts);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001260
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001261 raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001262}
1263
Lu Baolu6f7db752018-12-10 09:59:00 +08001264void iommu_flush_write_buffer(struct intel_iommu *iommu)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001265{
1266 u32 val;
1267 unsigned long flag;
1268
David Woodhouse9af88142009-02-13 23:18:03 +00001269 if (!rwbf_quirk && !cap_rwbf(iommu->cap))
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001270 return;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001271
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001272 raw_spin_lock_irqsave(&iommu->register_lock, flag);
David Woodhouse462b60f2009-05-10 20:18:18 +01001273 writel(iommu->gcmd | DMA_GCMD_WBF, iommu->reg + DMAR_GCMD_REG);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001274
1275 /* Make sure hardware complete it */
1276 IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
David Woodhousec416daa2009-05-10 20:30:58 +01001277 readl, (!(val & DMA_GSTS_WBFS)), val);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001278
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001279 raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001280}
1281
1282/* return value determine if we need a write buffer flush */
David Woodhouse4c25a2c2009-05-10 17:16:06 +01001283static void __iommu_flush_context(struct intel_iommu *iommu,
1284 u16 did, u16 source_id, u8 function_mask,
1285 u64 type)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001286{
1287 u64 val = 0;
1288 unsigned long flag;
1289
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001290 switch (type) {
1291 case DMA_CCMD_GLOBAL_INVL:
1292 val = DMA_CCMD_GLOBAL_INVL;
1293 break;
1294 case DMA_CCMD_DOMAIN_INVL:
1295 val = DMA_CCMD_DOMAIN_INVL|DMA_CCMD_DID(did);
1296 break;
1297 case DMA_CCMD_DEVICE_INVL:
1298 val = DMA_CCMD_DEVICE_INVL|DMA_CCMD_DID(did)
1299 | DMA_CCMD_SID(source_id) | DMA_CCMD_FM(function_mask);
1300 break;
1301 default:
1302 BUG();
1303 }
1304 val |= DMA_CCMD_ICC;
1305
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001306 raw_spin_lock_irqsave(&iommu->register_lock, flag);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001307 dmar_writeq(iommu->reg + DMAR_CCMD_REG, val);
1308
1309 /* Make sure hardware complete it */
1310 IOMMU_WAIT_OP(iommu, DMAR_CCMD_REG,
1311 dmar_readq, (!(val & DMA_CCMD_ICC)), val);
1312
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001313 raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001314}
1315
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001316/* return value determine if we need a write buffer flush */
David Woodhouse1f0ef2a2009-05-10 19:58:49 +01001317static void __iommu_flush_iotlb(struct intel_iommu *iommu, u16 did,
1318 u64 addr, unsigned int size_order, u64 type)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001319{
1320 int tlb_offset = ecap_iotlb_offset(iommu->ecap);
1321 u64 val = 0, val_iva = 0;
1322 unsigned long flag;
1323
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001324 switch (type) {
1325 case DMA_TLB_GLOBAL_FLUSH:
1326 /* global flush doesn't need set IVA_REG */
1327 val = DMA_TLB_GLOBAL_FLUSH|DMA_TLB_IVT;
1328 break;
1329 case DMA_TLB_DSI_FLUSH:
1330 val = DMA_TLB_DSI_FLUSH|DMA_TLB_IVT|DMA_TLB_DID(did);
1331 break;
1332 case DMA_TLB_PSI_FLUSH:
1333 val = DMA_TLB_PSI_FLUSH|DMA_TLB_IVT|DMA_TLB_DID(did);
David Woodhouseea8ea462014-03-05 17:09:32 +00001334 /* IH bit is passed in as part of address */
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001335 val_iva = size_order | addr;
1336 break;
1337 default:
1338 BUG();
1339 }
1340 /* Note: set drain read/write */
1341#if 0
1342 /*
1343 * This is probably to be super secure.. Looks like we can
1344 * ignore it without any impact.
1345 */
1346 if (cap_read_drain(iommu->cap))
1347 val |= DMA_TLB_READ_DRAIN;
1348#endif
1349 if (cap_write_drain(iommu->cap))
1350 val |= DMA_TLB_WRITE_DRAIN;
1351
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001352 raw_spin_lock_irqsave(&iommu->register_lock, flag);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001353 /* Note: Only uses first TLB reg currently */
1354 if (val_iva)
1355 dmar_writeq(iommu->reg + tlb_offset, val_iva);
1356 dmar_writeq(iommu->reg + tlb_offset + 8, val);
1357
1358 /* Make sure hardware complete it */
1359 IOMMU_WAIT_OP(iommu, tlb_offset + 8,
1360 dmar_readq, (!(val & DMA_TLB_IVT)), val);
1361
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001362 raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001363
1364 /* check IOTLB invalidation granularity */
1365 if (DMA_TLB_IAIG(val) == 0)
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02001366 pr_err("Flush IOTLB failed\n");
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001367 if (DMA_TLB_IAIG(val) != DMA_TLB_IIRG(type))
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02001368 pr_debug("TLB flush request %Lx, actual %Lx\n",
Fenghua Yu5b6985c2008-10-16 18:02:32 -07001369 (unsigned long long)DMA_TLB_IIRG(type),
1370 (unsigned long long)DMA_TLB_IAIG(val));
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001371}
1372
David Woodhouse64ae8922014-03-09 12:52:30 -07001373static struct device_domain_info *
1374iommu_support_dev_iotlb (struct dmar_domain *domain, struct intel_iommu *iommu,
1375 u8 bus, u8 devfn)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001376{
Yu Zhao93a23a72009-05-18 13:51:37 +08001377 struct device_domain_info *info;
Yu Zhao93a23a72009-05-18 13:51:37 +08001378
Joerg Roedel55d94042015-07-22 16:50:40 +02001379 assert_spin_locked(&device_domain_lock);
1380
Yu Zhao93a23a72009-05-18 13:51:37 +08001381 if (!iommu->qi)
1382 return NULL;
1383
Yu Zhao93a23a72009-05-18 13:51:37 +08001384 list_for_each_entry(info, &domain->devices, link)
Jiang Liuc3b497c2014-07-11 14:19:25 +08001385 if (info->iommu == iommu && info->bus == bus &&
1386 info->devfn == devfn) {
David Woodhouseb16d0cb2015-10-12 14:17:37 +01001387 if (info->ats_supported && info->dev)
1388 return info;
Yu Zhao93a23a72009-05-18 13:51:37 +08001389 break;
1390 }
Yu Zhao93a23a72009-05-18 13:51:37 +08001391
David Woodhouseb16d0cb2015-10-12 14:17:37 +01001392 return NULL;
Yu Zhao93a23a72009-05-18 13:51:37 +08001393}
1394
Omer Peleg0824c592016-04-20 19:03:35 +03001395static void domain_update_iotlb(struct dmar_domain *domain)
1396{
1397 struct device_domain_info *info;
1398 bool has_iotlb_device = false;
1399
1400 assert_spin_locked(&device_domain_lock);
1401
1402 list_for_each_entry(info, &domain->devices, link) {
1403 struct pci_dev *pdev;
1404
1405 if (!info->dev || !dev_is_pci(info->dev))
1406 continue;
1407
1408 pdev = to_pci_dev(info->dev);
1409 if (pdev->ats_enabled) {
1410 has_iotlb_device = true;
1411 break;
1412 }
1413 }
1414
1415 domain->has_iotlb_device = has_iotlb_device;
1416}
1417
Yu Zhao93a23a72009-05-18 13:51:37 +08001418static void iommu_enable_dev_iotlb(struct device_domain_info *info)
1419{
Bjorn Helgaasfb0cc3a2015-07-20 09:10:36 -05001420 struct pci_dev *pdev;
1421
Omer Peleg0824c592016-04-20 19:03:35 +03001422 assert_spin_locked(&device_domain_lock);
1423
David Woodhouse0bcb3e22014-03-06 17:12:03 +00001424 if (!info || !dev_is_pci(info->dev))
Yu Zhao93a23a72009-05-18 13:51:37 +08001425 return;
1426
Bjorn Helgaasfb0cc3a2015-07-20 09:10:36 -05001427 pdev = to_pci_dev(info->dev);
Jacob Pan1c48db42018-06-07 09:57:00 -07001428 /* For IOMMU that supports device IOTLB throttling (DIT), we assign
1429 * PFSID to the invalidation desc of a VF such that IOMMU HW can gauge
1430 * queue depth at PF level. If DIT is not set, PFSID will be treated as
1431 * reserved, which should be set to 0.
1432 */
1433 if (!ecap_dit(info->iommu->ecap))
1434 info->pfsid = 0;
1435 else {
1436 struct pci_dev *pf_pdev;
1437
1438 /* pdev will be returned if device is not a vf */
1439 pf_pdev = pci_physfn(pdev);
Heiner Kallweitcc49baa2019-04-24 21:16:10 +02001440 info->pfsid = pci_dev_id(pf_pdev);
Jacob Pan1c48db42018-06-07 09:57:00 -07001441 }
Bjorn Helgaasfb0cc3a2015-07-20 09:10:36 -05001442
David Woodhouseb16d0cb2015-10-12 14:17:37 +01001443#ifdef CONFIG_INTEL_IOMMU_SVM
1444 /* The PCIe spec, in its wisdom, declares that the behaviour of
1445 the device if you enable PASID support after ATS support is
1446 undefined. So always enable PASID support on devices which
1447 have it, even if we can't yet know if we're ever going to
1448 use it. */
1449 if (info->pasid_supported && !pci_enable_pasid(pdev, info->pasid_supported & ~1))
1450 info->pasid_enabled = 1;
1451
Kuppuswamy Sathyanarayanan1b84778a2019-02-19 11:04:52 -08001452 if (info->pri_supported &&
1453 (info->pasid_enabled ? pci_prg_resp_pasid_required(pdev) : 1) &&
1454 !pci_reset_pri(pdev) && !pci_enable_pri(pdev, 32))
David Woodhouseb16d0cb2015-10-12 14:17:37 +01001455 info->pri_enabled = 1;
1456#endif
Mika Westerbergfb58fdc2018-10-29 13:47:08 +03001457 if (!pdev->untrusted && info->ats_supported &&
Kuppuswamy Sathyanarayanan61363c12019-02-19 11:06:10 -08001458 pci_ats_page_aligned(pdev) &&
Mika Westerbergfb58fdc2018-10-29 13:47:08 +03001459 !pci_enable_ats(pdev, VTD_PAGE_SHIFT)) {
David Woodhouseb16d0cb2015-10-12 14:17:37 +01001460 info->ats_enabled = 1;
Omer Peleg0824c592016-04-20 19:03:35 +03001461 domain_update_iotlb(info->domain);
David Woodhouseb16d0cb2015-10-12 14:17:37 +01001462 info->ats_qdep = pci_ats_queue_depth(pdev);
1463 }
Yu Zhao93a23a72009-05-18 13:51:37 +08001464}
1465
1466static void iommu_disable_dev_iotlb(struct device_domain_info *info)
1467{
David Woodhouseb16d0cb2015-10-12 14:17:37 +01001468 struct pci_dev *pdev;
1469
Omer Peleg0824c592016-04-20 19:03:35 +03001470 assert_spin_locked(&device_domain_lock);
1471
Jeremy McNicollda972fb2016-01-14 21:33:06 -08001472 if (!dev_is_pci(info->dev))
Yu Zhao93a23a72009-05-18 13:51:37 +08001473 return;
1474
David Woodhouseb16d0cb2015-10-12 14:17:37 +01001475 pdev = to_pci_dev(info->dev);
1476
1477 if (info->ats_enabled) {
1478 pci_disable_ats(pdev);
1479 info->ats_enabled = 0;
Omer Peleg0824c592016-04-20 19:03:35 +03001480 domain_update_iotlb(info->domain);
David Woodhouseb16d0cb2015-10-12 14:17:37 +01001481 }
1482#ifdef CONFIG_INTEL_IOMMU_SVM
1483 if (info->pri_enabled) {
1484 pci_disable_pri(pdev);
1485 info->pri_enabled = 0;
1486 }
1487 if (info->pasid_enabled) {
1488 pci_disable_pasid(pdev);
1489 info->pasid_enabled = 0;
1490 }
1491#endif
Yu Zhao93a23a72009-05-18 13:51:37 +08001492}
1493
1494static void iommu_flush_dev_iotlb(struct dmar_domain *domain,
1495 u64 addr, unsigned mask)
1496{
1497 u16 sid, qdep;
1498 unsigned long flags;
1499 struct device_domain_info *info;
1500
Omer Peleg0824c592016-04-20 19:03:35 +03001501 if (!domain->has_iotlb_device)
1502 return;
1503
Yu Zhao93a23a72009-05-18 13:51:37 +08001504 spin_lock_irqsave(&device_domain_lock, flags);
1505 list_for_each_entry(info, &domain->devices, link) {
David Woodhouseb16d0cb2015-10-12 14:17:37 +01001506 if (!info->ats_enabled)
Yu Zhao93a23a72009-05-18 13:51:37 +08001507 continue;
1508
1509 sid = info->bus << 8 | info->devfn;
David Woodhouseb16d0cb2015-10-12 14:17:37 +01001510 qdep = info->ats_qdep;
Jacob Pan1c48db42018-06-07 09:57:00 -07001511 qi_flush_dev_iotlb(info->iommu, sid, info->pfsid,
1512 qdep, addr, mask);
Yu Zhao93a23a72009-05-18 13:51:37 +08001513 }
1514 spin_unlock_irqrestore(&device_domain_lock, flags);
1515}
1516
Lu Baolu33cd6e62020-01-02 08:18:18 +08001517static void domain_flush_piotlb(struct intel_iommu *iommu,
1518 struct dmar_domain *domain,
1519 u64 addr, unsigned long npages, bool ih)
1520{
1521 u16 did = domain->iommu_did[iommu->seq_id];
1522
1523 if (domain->default_pasid)
1524 qi_flush_piotlb(iommu, did, domain->default_pasid,
1525 addr, npages, ih);
1526
1527 if (!list_empty(&domain->devices))
1528 qi_flush_piotlb(iommu, did, PASID_RID2PASID, addr, npages, ih);
1529}
1530
Joerg Roedela1ddcbe2015-07-21 15:20:32 +02001531static void iommu_flush_iotlb_psi(struct intel_iommu *iommu,
1532 struct dmar_domain *domain,
1533 unsigned long pfn, unsigned int pages,
1534 int ih, int map)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001535{
Yu Zhao9dd2fe82009-05-18 13:51:36 +08001536 unsigned int mask = ilog2(__roundup_pow_of_two(pages));
David Woodhouse03d6a242009-06-28 15:33:46 +01001537 uint64_t addr = (uint64_t)pfn << VTD_PAGE_SHIFT;
Joerg Roedela1ddcbe2015-07-21 15:20:32 +02001538 u16 did = domain->iommu_did[iommu->seq_id];
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001539
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001540 BUG_ON(pages == 0);
1541
David Woodhouseea8ea462014-03-05 17:09:32 +00001542 if (ih)
1543 ih = 1 << 6;
Lu Baolu33cd6e62020-01-02 08:18:18 +08001544
1545 if (domain_use_first_level(domain)) {
1546 domain_flush_piotlb(iommu, domain, addr, pages, ih);
1547 } else {
1548 /*
1549 * Fallback to domain selective flush if no PSI support or
1550 * the size is too big. PSI requires page size to be 2 ^ x,
1551 * and the base address is naturally aligned to the size.
1552 */
1553 if (!cap_pgsel_inv(iommu->cap) ||
1554 mask > cap_max_amask_val(iommu->cap))
1555 iommu->flush.flush_iotlb(iommu, did, 0, 0,
1556 DMA_TLB_DSI_FLUSH);
1557 else
1558 iommu->flush.flush_iotlb(iommu, did, addr | ih, mask,
1559 DMA_TLB_PSI_FLUSH);
1560 }
Yu Zhaobf92df32009-06-29 11:31:45 +08001561
1562 /*
Nadav Amit82653632010-04-01 13:24:40 +03001563 * In caching mode, changes of pages from non-present to present require
1564 * flush. However, device IOTLB doesn't need to be flushed in this case.
Yu Zhaobf92df32009-06-29 11:31:45 +08001565 */
Nadav Amit82653632010-04-01 13:24:40 +03001566 if (!cap_caching_mode(iommu->cap) || !map)
Peter Xu9d2e6502018-01-10 13:51:37 +08001567 iommu_flush_dev_iotlb(domain, addr, mask);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001568}
1569
Peter Xueed91a02018-05-04 10:34:52 +08001570/* Notification for newly created mappings */
1571static inline void __mapping_notify_one(struct intel_iommu *iommu,
1572 struct dmar_domain *domain,
1573 unsigned long pfn, unsigned int pages)
1574{
Lu Baolu33cd6e62020-01-02 08:18:18 +08001575 /*
1576 * It's a non-present to present mapping. Only flush if caching mode
1577 * and second level.
1578 */
1579 if (cap_caching_mode(iommu->cap) && !domain_use_first_level(domain))
Peter Xueed91a02018-05-04 10:34:52 +08001580 iommu_flush_iotlb_psi(iommu, domain, pfn, pages, 0, 1);
1581 else
1582 iommu_flush_write_buffer(iommu);
1583}
1584
Joerg Roedel13cf0172017-08-11 11:40:10 +02001585static void iommu_flush_iova(struct iova_domain *iovad)
1586{
1587 struct dmar_domain *domain;
1588 int idx;
1589
1590 domain = container_of(iovad, struct dmar_domain, iovad);
1591
1592 for_each_domain_iommu(idx, domain) {
1593 struct intel_iommu *iommu = g_iommus[idx];
1594 u16 did = domain->iommu_did[iommu->seq_id];
1595
Lu Baolu33cd6e62020-01-02 08:18:18 +08001596 if (domain_use_first_level(domain))
1597 domain_flush_piotlb(iommu, domain, 0, -1, 0);
1598 else
1599 iommu->flush.flush_iotlb(iommu, did, 0, 0,
1600 DMA_TLB_DSI_FLUSH);
Joerg Roedel13cf0172017-08-11 11:40:10 +02001601
1602 if (!cap_caching_mode(iommu->cap))
1603 iommu_flush_dev_iotlb(get_iommu_domain(iommu, did),
1604 0, MAX_AGAW_PFN_WIDTH);
1605 }
1606}
1607
mark grossf8bab732008-02-08 04:18:38 -08001608static void iommu_disable_protect_mem_regions(struct intel_iommu *iommu)
1609{
1610 u32 pmen;
1611 unsigned long flags;
1612
Lu Baolu5bb71fc72019-03-20 09:58:33 +08001613 if (!cap_plmr(iommu->cap) && !cap_phmr(iommu->cap))
1614 return;
1615
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001616 raw_spin_lock_irqsave(&iommu->register_lock, flags);
mark grossf8bab732008-02-08 04:18:38 -08001617 pmen = readl(iommu->reg + DMAR_PMEN_REG);
1618 pmen &= ~DMA_PMEN_EPM;
1619 writel(pmen, iommu->reg + DMAR_PMEN_REG);
1620
1621 /* wait for the protected region status bit to clear */
1622 IOMMU_WAIT_OP(iommu, DMAR_PMEN_REG,
1623 readl, !(pmen & DMA_PMEN_PRS), pmen);
1624
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001625 raw_spin_unlock_irqrestore(&iommu->register_lock, flags);
mark grossf8bab732008-02-08 04:18:38 -08001626}
1627
Jiang Liu2a41cce2014-07-11 14:19:33 +08001628static void iommu_enable_translation(struct intel_iommu *iommu)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001629{
1630 u32 sts;
1631 unsigned long flags;
1632
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001633 raw_spin_lock_irqsave(&iommu->register_lock, flags);
David Woodhousec416daa2009-05-10 20:30:58 +01001634 iommu->gcmd |= DMA_GCMD_TE;
1635 writel(iommu->gcmd, iommu->reg + DMAR_GCMD_REG);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001636
1637 /* Make sure hardware complete it */
1638 IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
David Woodhousec416daa2009-05-10 20:30:58 +01001639 readl, (sts & DMA_GSTS_TES), sts);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001640
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001641 raw_spin_unlock_irqrestore(&iommu->register_lock, flags);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001642}
1643
Jiang Liu2a41cce2014-07-11 14:19:33 +08001644static void iommu_disable_translation(struct intel_iommu *iommu)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001645{
1646 u32 sts;
1647 unsigned long flag;
1648
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001649 raw_spin_lock_irqsave(&iommu->register_lock, flag);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001650 iommu->gcmd &= ~DMA_GCMD_TE;
1651 writel(iommu->gcmd, iommu->reg + DMAR_GCMD_REG);
1652
1653 /* Make sure hardware complete it */
1654 IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
David Woodhousec416daa2009-05-10 20:30:58 +01001655 readl, (!(sts & DMA_GSTS_TES)), sts);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001656
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02001657 raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001658}
1659
1660static int iommu_init_domains(struct intel_iommu *iommu)
1661{
Joerg Roedel8bf47812015-07-21 10:41:21 +02001662 u32 ndomains, nlongs;
1663 size_t size;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001664
1665 ndomains = cap_ndoms(iommu->cap);
Joerg Roedel8bf47812015-07-21 10:41:21 +02001666 pr_debug("%s: Number of Domains supported <%d>\n",
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02001667 iommu->name, ndomains);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001668 nlongs = BITS_TO_LONGS(ndomains);
1669
Donald Dutile94a91b502009-08-20 16:51:34 -04001670 spin_lock_init(&iommu->lock);
1671
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001672 iommu->domain_ids = kcalloc(nlongs, sizeof(unsigned long), GFP_KERNEL);
1673 if (!iommu->domain_ids) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02001674 pr_err("%s: Allocating domain id array failed\n",
1675 iommu->name);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001676 return -ENOMEM;
1677 }
Joerg Roedel8bf47812015-07-21 10:41:21 +02001678
Wei Yang86f004c2016-05-21 02:41:51 +00001679 size = (ALIGN(ndomains, 256) >> 8) * sizeof(struct dmar_domain **);
Joerg Roedel8bf47812015-07-21 10:41:21 +02001680 iommu->domains = kzalloc(size, GFP_KERNEL);
1681
1682 if (iommu->domains) {
1683 size = 256 * sizeof(struct dmar_domain *);
1684 iommu->domains[0] = kzalloc(size, GFP_KERNEL);
1685 }
1686
1687 if (!iommu->domains || !iommu->domains[0]) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02001688 pr_err("%s: Allocating domain array failed\n",
1689 iommu->name);
Jiang Liu852bdb02014-01-06 14:18:11 +08001690 kfree(iommu->domain_ids);
Joerg Roedel8bf47812015-07-21 10:41:21 +02001691 kfree(iommu->domains);
Jiang Liu852bdb02014-01-06 14:18:11 +08001692 iommu->domain_ids = NULL;
Joerg Roedel8bf47812015-07-21 10:41:21 +02001693 iommu->domains = NULL;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001694 return -ENOMEM;
1695 }
1696
1697 /*
Joerg Roedelc0e8a6c2015-07-21 09:39:46 +02001698 * If Caching mode is set, then invalid translations are tagged
1699 * with domain-id 0, hence we need to pre-allocate it. We also
1700 * use domain-id 0 as a marker for non-allocated domain-id, so
1701 * make sure it is not used for a real domain.
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001702 */
Joerg Roedelc0e8a6c2015-07-21 09:39:46 +02001703 set_bit(0, iommu->domain_ids);
1704
Lu Baolu3b33d4a2018-12-10 09:58:59 +08001705 /*
1706 * Vt-d spec rev3.0 (section 6.2.3.1) requires that each pasid
1707 * entry for first-level or pass-through translation modes should
1708 * be programmed with a domain id different from those used for
1709 * second-level or nested translation. We reserve a domain id for
1710 * this purpose.
1711 */
1712 if (sm_supported(iommu))
1713 set_bit(FLPT_DEFAULT_DID, iommu->domain_ids);
1714
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001715 return 0;
1716}
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001717
Jiang Liuffebeb42014-11-09 22:48:02 +08001718static void disable_dmar_iommu(struct intel_iommu *iommu)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001719{
Joerg Roedel29a27712015-07-21 17:17:12 +02001720 struct device_domain_info *info, *tmp;
Joerg Roedel55d94042015-07-22 16:50:40 +02001721 unsigned long flags;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001722
Joerg Roedel29a27712015-07-21 17:17:12 +02001723 if (!iommu->domains || !iommu->domain_ids)
1724 return;
Jiang Liua4eaa862014-02-19 14:07:30 +08001725
Joerg Roedel55d94042015-07-22 16:50:40 +02001726 spin_lock_irqsave(&device_domain_lock, flags);
Joerg Roedel29a27712015-07-21 17:17:12 +02001727 list_for_each_entry_safe(info, tmp, &device_domain_list, global) {
Joerg Roedel29a27712015-07-21 17:17:12 +02001728 if (info->iommu != iommu)
1729 continue;
1730
1731 if (!info->dev || !info->domain)
1732 continue;
1733
Joerg Roedelbea64032016-11-08 15:08:26 +01001734 __dmar_remove_one_dev_info(info);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001735 }
Joerg Roedel55d94042015-07-22 16:50:40 +02001736 spin_unlock_irqrestore(&device_domain_lock, flags);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001737
1738 if (iommu->gcmd & DMA_GCMD_TE)
1739 iommu_disable_translation(iommu);
Jiang Liuffebeb42014-11-09 22:48:02 +08001740}
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001741
Jiang Liuffebeb42014-11-09 22:48:02 +08001742static void free_dmar_iommu(struct intel_iommu *iommu)
1743{
1744 if ((iommu->domains) && (iommu->domain_ids)) {
Wei Yang86f004c2016-05-21 02:41:51 +00001745 int elems = ALIGN(cap_ndoms(iommu->cap), 256) >> 8;
Joerg Roedel8bf47812015-07-21 10:41:21 +02001746 int i;
1747
1748 for (i = 0; i < elems; i++)
1749 kfree(iommu->domains[i]);
Jiang Liuffebeb42014-11-09 22:48:02 +08001750 kfree(iommu->domains);
1751 kfree(iommu->domain_ids);
1752 iommu->domains = NULL;
1753 iommu->domain_ids = NULL;
1754 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001755
Weidong Hand9630fe2008-12-08 11:06:32 +08001756 g_iommus[iommu->seq_id] = NULL;
1757
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001758 /* free context mapping */
1759 free_context_table(iommu);
David Woodhouse8a94ade2015-03-24 14:54:56 +00001760
1761#ifdef CONFIG_INTEL_IOMMU_SVM
Lu Baolu765b6a92018-12-10 09:58:55 +08001762 if (pasid_supported(iommu)) {
David Woodhousea222a7f2015-10-07 23:35:18 +01001763 if (ecap_prs(iommu->ecap))
1764 intel_svm_finish_prq(iommu);
David Woodhousea222a7f2015-10-07 23:35:18 +01001765 }
David Woodhouse8a94ade2015-03-24 14:54:56 +00001766#endif
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001767}
1768
Lu Baolua1948f22020-01-02 08:18:14 +08001769/*
1770 * Check and return whether first level is used by default for
Lu Baolub802d072020-01-02 08:18:21 +08001771 * DMA translation.
Lu Baolua1948f22020-01-02 08:18:14 +08001772 */
1773static bool first_level_by_default(void)
1774{
1775 struct dmar_drhd_unit *drhd;
1776 struct intel_iommu *iommu;
Lu Baolub802d072020-01-02 08:18:21 +08001777 static int first_level_support = -1;
Lu Baolua1948f22020-01-02 08:18:14 +08001778
1779 if (likely(first_level_support != -1))
1780 return first_level_support;
1781
1782 first_level_support = 1;
1783
1784 rcu_read_lock();
1785 for_each_active_iommu(iommu, drhd) {
1786 if (!sm_supported(iommu) || !ecap_flts(iommu->ecap)) {
1787 first_level_support = 0;
1788 break;
1789 }
1790 }
1791 rcu_read_unlock();
1792
1793 return first_level_support;
1794}
1795
Jiang Liuab8dfe22014-07-11 14:19:27 +08001796static struct dmar_domain *alloc_domain(int flags)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001797{
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001798 struct dmar_domain *domain;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001799
1800 domain = alloc_domain_mem();
1801 if (!domain)
1802 return NULL;
1803
Jiang Liuab8dfe22014-07-11 14:19:27 +08001804 memset(domain, 0, sizeof(*domain));
Anshuman Khandual98fa15f2019-03-05 15:42:58 -08001805 domain->nid = NUMA_NO_NODE;
Jiang Liuab8dfe22014-07-11 14:19:27 +08001806 domain->flags = flags;
Lu Baolua1948f22020-01-02 08:18:14 +08001807 if (first_level_by_default())
1808 domain->flags |= DOMAIN_FLAG_USE_FIRST_LEVEL;
Omer Peleg0824c592016-04-20 19:03:35 +03001809 domain->has_iotlb_device = false;
Jiang Liu92d03cc2014-02-19 14:07:28 +08001810 INIT_LIST_HEAD(&domain->devices);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001811
1812 return domain;
1813}
1814
Joerg Roedeld160aca2015-07-22 11:52:53 +02001815/* Must be called with iommu->lock */
1816static int domain_attach_iommu(struct dmar_domain *domain,
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07001817 struct intel_iommu *iommu)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001818{
Jiang Liu44bde612014-07-11 14:19:29 +08001819 unsigned long ndomains;
Joerg Roedel55d94042015-07-22 16:50:40 +02001820 int num;
Jiang Liu44bde612014-07-11 14:19:29 +08001821
Joerg Roedel55d94042015-07-22 16:50:40 +02001822 assert_spin_locked(&device_domain_lock);
Joerg Roedeld160aca2015-07-22 11:52:53 +02001823 assert_spin_locked(&iommu->lock);
Jiang Liu44bde612014-07-11 14:19:29 +08001824
Joerg Roedel29a27712015-07-21 17:17:12 +02001825 domain->iommu_refcnt[iommu->seq_id] += 1;
1826 domain->iommu_count += 1;
1827 if (domain->iommu_refcnt[iommu->seq_id] == 1) {
Jiang Liufb170fb2014-07-11 14:19:28 +08001828 ndomains = cap_ndoms(iommu->cap);
Joerg Roedeld160aca2015-07-22 11:52:53 +02001829 num = find_first_zero_bit(iommu->domain_ids, ndomains);
1830
1831 if (num >= ndomains) {
1832 pr_err("%s: No free domain ids\n", iommu->name);
1833 domain->iommu_refcnt[iommu->seq_id] -= 1;
1834 domain->iommu_count -= 1;
Joerg Roedel55d94042015-07-22 16:50:40 +02001835 return -ENOSPC;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07001836 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001837
Joerg Roedeld160aca2015-07-22 11:52:53 +02001838 set_bit(num, iommu->domain_ids);
1839 set_iommu_domain(iommu, num, domain);
Jiang Liufb170fb2014-07-11 14:19:28 +08001840
Joerg Roedeld160aca2015-07-22 11:52:53 +02001841 domain->iommu_did[iommu->seq_id] = num;
1842 domain->nid = iommu->node;
1843
Jiang Liufb170fb2014-07-11 14:19:28 +08001844 domain_update_iommu_cap(domain);
1845 }
Joerg Roedeld160aca2015-07-22 11:52:53 +02001846
Joerg Roedel55d94042015-07-22 16:50:40 +02001847 return 0;
Jiang Liufb170fb2014-07-11 14:19:28 +08001848}
1849
1850static int domain_detach_iommu(struct dmar_domain *domain,
1851 struct intel_iommu *iommu)
1852{
Bjorn Helgaase083ea5b2019-02-08 16:06:08 -06001853 int num, count;
Jiang Liufb170fb2014-07-11 14:19:28 +08001854
Joerg Roedel55d94042015-07-22 16:50:40 +02001855 assert_spin_locked(&device_domain_lock);
Joerg Roedeld160aca2015-07-22 11:52:53 +02001856 assert_spin_locked(&iommu->lock);
Jiang Liufb170fb2014-07-11 14:19:28 +08001857
Joerg Roedel29a27712015-07-21 17:17:12 +02001858 domain->iommu_refcnt[iommu->seq_id] -= 1;
1859 count = --domain->iommu_count;
1860 if (domain->iommu_refcnt[iommu->seq_id] == 0) {
Joerg Roedeld160aca2015-07-22 11:52:53 +02001861 num = domain->iommu_did[iommu->seq_id];
1862 clear_bit(num, iommu->domain_ids);
1863 set_iommu_domain(iommu, num, NULL);
1864
Jiang Liufb170fb2014-07-11 14:19:28 +08001865 domain_update_iommu_cap(domain);
Joerg Roedelc0e8a6c2015-07-21 09:39:46 +02001866 domain->iommu_did[iommu->seq_id] = 0;
Jiang Liufb170fb2014-07-11 14:19:28 +08001867 }
Jiang Liufb170fb2014-07-11 14:19:28 +08001868
1869 return count;
1870}
1871
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001872static struct iova_domain reserved_iova_list;
Mark Gross8a443df2008-03-04 14:59:31 -08001873static struct lock_class_key reserved_rbtree_key;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001874
Joseph Cihula51a63e62011-03-21 11:04:24 -07001875static int dmar_init_reserved_ranges(void)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001876{
1877 struct pci_dev *pdev = NULL;
1878 struct iova *iova;
1879 int i;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001880
Zhen Leiaa3ac942017-09-21 16:52:45 +01001881 init_iova_domain(&reserved_iova_list, VTD_PAGE_SIZE, IOVA_START_PFN);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001882
Mark Gross8a443df2008-03-04 14:59:31 -08001883 lockdep_set_class(&reserved_iova_list.iova_rbtree_lock,
1884 &reserved_rbtree_key);
1885
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001886 /* IOAPIC ranges shouldn't be accessed by DMA */
1887 iova = reserve_iova(&reserved_iova_list, IOVA_PFN(IOAPIC_RANGE_START),
1888 IOVA_PFN(IOAPIC_RANGE_END));
Joseph Cihula51a63e62011-03-21 11:04:24 -07001889 if (!iova) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02001890 pr_err("Reserve IOAPIC range failed\n");
Joseph Cihula51a63e62011-03-21 11:04:24 -07001891 return -ENODEV;
1892 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001893
1894 /* Reserve all PCI MMIO to avoid peer-to-peer access */
1895 for_each_pci_dev(pdev) {
1896 struct resource *r;
1897
1898 for (i = 0; i < PCI_NUM_RESOURCES; i++) {
1899 r = &pdev->resource[i];
1900 if (!r->flags || !(r->flags & IORESOURCE_MEM))
1901 continue;
David Woodhouse1a4a4552009-06-28 16:00:42 +01001902 iova = reserve_iova(&reserved_iova_list,
1903 IOVA_PFN(r->start),
1904 IOVA_PFN(r->end));
Joseph Cihula51a63e62011-03-21 11:04:24 -07001905 if (!iova) {
Bjorn Helgaas932a6522019-02-08 16:06:00 -06001906 pci_err(pdev, "Reserve iova for %pR failed\n", r);
Joseph Cihula51a63e62011-03-21 11:04:24 -07001907 return -ENODEV;
1908 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001909 }
1910 }
Joseph Cihula51a63e62011-03-21 11:04:24 -07001911 return 0;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001912}
1913
1914static void domain_reserve_special_ranges(struct dmar_domain *domain)
1915{
1916 copy_reserved_iova(&reserved_iova_list, &domain->iovad);
1917}
1918
1919static inline int guestwidth_to_adjustwidth(int gaw)
1920{
1921 int agaw;
1922 int r = (gaw - 12) % 9;
1923
1924 if (r == 0)
1925 agaw = gaw;
1926 else
1927 agaw = gaw + 9 - r;
1928 if (agaw > 64)
1929 agaw = 64;
1930 return agaw;
1931}
1932
Joerg Roedel301e7ee2019-07-22 16:21:05 +02001933static int domain_init(struct dmar_domain *domain, struct intel_iommu *iommu,
1934 int guest_width)
1935{
1936 int adjust_width, agaw;
1937 unsigned long sagaw;
Lu Baolu8e3391c2020-01-02 08:18:13 +08001938 int ret;
Joerg Roedel301e7ee2019-07-22 16:21:05 +02001939
1940 init_iova_domain(&domain->iovad, VTD_PAGE_SIZE, IOVA_START_PFN);
1941
Lu Baolu10f80082020-01-02 08:18:12 +08001942 if (!intel_iommu_strict) {
Lu Baolu8e3391c2020-01-02 08:18:13 +08001943 ret = init_iova_flush_queue(&domain->iovad,
Lu Baolu10f80082020-01-02 08:18:12 +08001944 iommu_flush_iova, iova_entry_free);
Lu Baolu8e3391c2020-01-02 08:18:13 +08001945 if (ret)
1946 pr_info("iova flush queue initialization failed\n");
Lu Baolu10f80082020-01-02 08:18:12 +08001947 }
Joerg Roedel301e7ee2019-07-22 16:21:05 +02001948
1949 domain_reserve_special_ranges(domain);
1950
1951 /* calculate AGAW */
1952 if (guest_width > cap_mgaw(iommu->cap))
1953 guest_width = cap_mgaw(iommu->cap);
1954 domain->gaw = guest_width;
1955 adjust_width = guestwidth_to_adjustwidth(guest_width);
1956 agaw = width_to_agaw(adjust_width);
1957 sagaw = cap_sagaw(iommu->cap);
1958 if (!test_bit(agaw, &sagaw)) {
1959 /* hardware doesn't support it, choose a bigger one */
1960 pr_debug("Hardware doesn't support agaw %d\n", agaw);
1961 agaw = find_next_bit(&sagaw, 5, agaw);
1962 if (agaw >= 5)
1963 return -ENODEV;
1964 }
1965 domain->agaw = agaw;
1966
1967 if (ecap_coherent(iommu->ecap))
1968 domain->iommu_coherency = 1;
1969 else
1970 domain->iommu_coherency = 0;
1971
1972 if (ecap_sc_support(iommu->ecap))
1973 domain->iommu_snooping = 1;
1974 else
1975 domain->iommu_snooping = 0;
1976
1977 if (intel_iommu_superpage)
1978 domain->iommu_superpage = fls(cap_super_page_val(iommu->cap));
1979 else
1980 domain->iommu_superpage = 0;
1981
1982 domain->nid = iommu->node;
1983
1984 /* always allocate the top pgd */
1985 domain->pgd = (struct dma_pte *)alloc_pgtable_page(domain->nid);
1986 if (!domain->pgd)
1987 return -ENOMEM;
1988 __iommu_flush_cache(iommu, domain->pgd, PAGE_SIZE);
1989 return 0;
1990}
1991
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001992static void domain_exit(struct dmar_domain *domain)
1993{
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001994
Joerg Roedeld160aca2015-07-22 11:52:53 +02001995 /* Remove associated devices and clear attached or cached domains */
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001996 domain_remove_dev_info(domain);
Jiang Liu92d03cc2014-02-19 14:07:28 +08001997
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07001998 /* destroy iovas */
1999 put_iova_domain(&domain->iovad);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002000
Dmitry Safonov3ee9eca2019-07-16 22:38:06 +01002001 if (domain->pgd) {
2002 struct page *freelist;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002003
Dmitry Safonov3ee9eca2019-07-16 22:38:06 +01002004 freelist = domain_unmap(domain, 0, DOMAIN_MAX_PFN(domain->gaw));
2005 dma_free_pagelist(freelist);
2006 }
David Woodhouseea8ea462014-03-05 17:09:32 +00002007
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002008 free_domain_mem(domain);
2009}
2010
Lu Baolu7373a8c2018-12-10 09:59:03 +08002011/*
2012 * Get the PASID directory size for scalable mode context entry.
2013 * Value of X in the PDTS field of a scalable mode context entry
2014 * indicates PASID directory with 2^(X + 7) entries.
2015 */
2016static inline unsigned long context_get_sm_pds(struct pasid_table *table)
2017{
2018 int pds, max_pde;
2019
2020 max_pde = table->max_pasid >> PASID_PDE_SHIFT;
2021 pds = find_first_bit((unsigned long *)&max_pde, MAX_NR_PASID_BITS);
2022 if (pds < 7)
2023 return 0;
2024
2025 return pds - 7;
2026}
2027
2028/*
2029 * Set the RID_PASID field of a scalable mode context entry. The
2030 * IOMMU hardware will use the PASID value set in this field for
2031 * DMA translations of DMA requests without PASID.
2032 */
2033static inline void
2034context_set_sm_rid2pasid(struct context_entry *context, unsigned long pasid)
2035{
2036 context->hi |= pasid & ((1 << 20) - 1);
2037 context->hi |= (1 << 20);
2038}
2039
2040/*
2041 * Set the DTE(Device-TLB Enable) field of a scalable mode context
2042 * entry.
2043 */
2044static inline void context_set_sm_dte(struct context_entry *context)
2045{
2046 context->lo |= (1 << 2);
2047}
2048
2049/*
2050 * Set the PRE(Page Request Enable) field of a scalable mode context
2051 * entry.
2052 */
2053static inline void context_set_sm_pre(struct context_entry *context)
2054{
2055 context->lo |= (1 << 4);
2056}
2057
2058/* Convert value to context PASID directory size field coding. */
2059#define context_pdts(pds) (((pds) & 0x7) << 9)
2060
David Woodhouse64ae8922014-03-09 12:52:30 -07002061static int domain_context_mapping_one(struct dmar_domain *domain,
2062 struct intel_iommu *iommu,
Lu Baoluca6e3222018-12-10 09:59:02 +08002063 struct pasid_table *table,
Joerg Roedel28ccce02015-07-21 14:45:31 +02002064 u8 bus, u8 devfn)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002065{
Joerg Roedelc6c2ceb2015-07-22 13:11:53 +02002066 u16 did = domain->iommu_did[iommu->seq_id];
Joerg Roedel28ccce02015-07-21 14:45:31 +02002067 int translation = CONTEXT_TT_MULTI_LEVEL;
2068 struct device_domain_info *info = NULL;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002069 struct context_entry *context;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002070 unsigned long flags;
Lu Baolu7373a8c2018-12-10 09:59:03 +08002071 int ret;
Joerg Roedel28ccce02015-07-21 14:45:31 +02002072
Joerg Roedelc6c2ceb2015-07-22 13:11:53 +02002073 WARN_ON(did == 0);
2074
Joerg Roedel28ccce02015-07-21 14:45:31 +02002075 if (hw_pass_through && domain_type_is_si(domain))
2076 translation = CONTEXT_TT_PASS_THROUGH;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002077
2078 pr_debug("Set context mapping for %02x:%02x.%d\n",
2079 bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07002080
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002081 BUG_ON(!domain->pgd);
Weidong Han5331fe62008-12-08 23:00:00 +08002082
Joerg Roedel55d94042015-07-22 16:50:40 +02002083 spin_lock_irqsave(&device_domain_lock, flags);
2084 spin_lock(&iommu->lock);
2085
2086 ret = -ENOMEM;
David Woodhouse03ecc322015-02-13 14:35:21 +00002087 context = iommu_context_addr(iommu, bus, devfn, 1);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002088 if (!context)
Joerg Roedel55d94042015-07-22 16:50:40 +02002089 goto out_unlock;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002090
Joerg Roedel55d94042015-07-22 16:50:40 +02002091 ret = 0;
2092 if (context_present(context))
2093 goto out_unlock;
Joerg Roedelcf484d02015-06-12 12:21:46 +02002094
Xunlei Pangaec0e862016-12-05 20:09:07 +08002095 /*
2096 * For kdump cases, old valid entries may be cached due to the
2097 * in-flight DMA and copied pgtable, but there is no unmapping
2098 * behaviour for them, thus we need an explicit cache flush for
2099 * the newly-mapped device. For kdump, at this point, the device
2100 * is supposed to finish reset at its driver probe stage, so no
2101 * in-flight DMA will exist, and we don't need to worry anymore
2102 * hereafter.
2103 */
2104 if (context_copied(context)) {
2105 u16 did_old = context_domain_id(context);
2106
Christos Gkekasb117e032017-10-08 23:33:31 +01002107 if (did_old < cap_ndoms(iommu->cap)) {
Xunlei Pangaec0e862016-12-05 20:09:07 +08002108 iommu->flush.flush_context(iommu, did_old,
2109 (((u16)bus) << 8) | devfn,
2110 DMA_CCMD_MASK_NOBIT,
2111 DMA_CCMD_DEVICE_INVL);
KarimAllah Ahmedf73a7ee2017-05-05 11:39:59 -07002112 iommu->flush.flush_iotlb(iommu, did_old, 0, 0,
2113 DMA_TLB_DSI_FLUSH);
2114 }
Xunlei Pangaec0e862016-12-05 20:09:07 +08002115 }
2116
Joerg Roedelde24e552015-07-21 14:53:04 +02002117 context_clear_entry(context);
Weidong Hanea6606b2008-12-08 23:08:15 +08002118
Lu Baolu7373a8c2018-12-10 09:59:03 +08002119 if (sm_supported(iommu)) {
2120 unsigned long pds;
Joerg Roedelde24e552015-07-21 14:53:04 +02002121
Lu Baolu7373a8c2018-12-10 09:59:03 +08002122 WARN_ON(!table);
2123
2124 /* Setup the PASID DIR pointer: */
2125 pds = context_get_sm_pds(table);
2126 context->lo = (u64)virt_to_phys(table->table) |
2127 context_pdts(pds);
2128
2129 /* Setup the RID_PASID field: */
2130 context_set_sm_rid2pasid(context, PASID_RID2PASID);
2131
2132 /*
2133 * Setup the Device-TLB enable bit and Page request
2134 * Enable bit:
2135 */
David Woodhouse64ae8922014-03-09 12:52:30 -07002136 info = iommu_support_dev_iotlb(domain, iommu, bus, devfn);
David Woodhouseb16d0cb2015-10-12 14:17:37 +01002137 if (info && info->ats_supported)
Lu Baolu7373a8c2018-12-10 09:59:03 +08002138 context_set_sm_dte(context);
2139 if (info && info->pri_supported)
2140 context_set_sm_pre(context);
Joerg Roedelde24e552015-07-21 14:53:04 +02002141 } else {
Lu Baolu7373a8c2018-12-10 09:59:03 +08002142 struct dma_pte *pgd = domain->pgd;
2143 int agaw;
2144
2145 context_set_domain_id(context, did);
Lu Baolu7373a8c2018-12-10 09:59:03 +08002146
2147 if (translation != CONTEXT_TT_PASS_THROUGH) {
2148 /*
2149 * Skip top levels of page tables for iommu which has
2150 * less agaw than default. Unnecessary for PT mode.
2151 */
2152 for (agaw = domain->agaw; agaw > iommu->agaw; agaw--) {
2153 ret = -ENOMEM;
2154 pgd = phys_to_virt(dma_pte_addr(pgd));
2155 if (!dma_pte_present(pgd))
2156 goto out_unlock;
2157 }
2158
2159 info = iommu_support_dev_iotlb(domain, iommu, bus, devfn);
2160 if (info && info->ats_supported)
2161 translation = CONTEXT_TT_DEV_IOTLB;
2162 else
2163 translation = CONTEXT_TT_MULTI_LEVEL;
2164
2165 context_set_address_root(context, virt_to_phys(pgd));
2166 context_set_address_width(context, agaw);
2167 } else {
2168 /*
2169 * In pass through mode, AW must be programmed to
2170 * indicate the largest AGAW value supported by
2171 * hardware. And ASR is ignored by hardware.
2172 */
2173 context_set_address_width(context, iommu->msagaw);
2174 }
Lu Baolu41b80db2019-03-01 11:23:11 +08002175
2176 context_set_translation_type(context, translation);
Yu Zhao93a23a72009-05-18 13:51:37 +08002177 }
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07002178
Mark McLoughlinc07e7d22008-11-21 16:54:46 +00002179 context_set_fault_enable(context);
2180 context_set_present(context);
Weidong Han5331fe62008-12-08 23:00:00 +08002181 domain_flush_cache(domain, context, sizeof(*context));
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002182
David Woodhouse4c25a2c2009-05-10 17:16:06 +01002183 /*
2184 * It's a non-present to present mapping. If hardware doesn't cache
2185 * non-present entry we only need to flush the write-buffer. If the
2186 * _does_ cache non-present entries, then it does so in the special
2187 * domain #0, which we have to flush:
2188 */
2189 if (cap_caching_mode(iommu->cap)) {
2190 iommu->flush.flush_context(iommu, 0,
2191 (((u16)bus) << 8) | devfn,
2192 DMA_CCMD_MASK_NOBIT,
2193 DMA_CCMD_DEVICE_INVL);
Joerg Roedelc6c2ceb2015-07-22 13:11:53 +02002194 iommu->flush.flush_iotlb(iommu, did, 0, 0, DMA_TLB_DSI_FLUSH);
David Woodhouse4c25a2c2009-05-10 17:16:06 +01002195 } else {
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002196 iommu_flush_write_buffer(iommu);
David Woodhouse4c25a2c2009-05-10 17:16:06 +01002197 }
Yu Zhao93a23a72009-05-18 13:51:37 +08002198 iommu_enable_dev_iotlb(info);
Weidong Hanc7151a82008-12-08 22:51:37 +08002199
Joerg Roedel55d94042015-07-22 16:50:40 +02002200 ret = 0;
2201
2202out_unlock:
2203 spin_unlock(&iommu->lock);
2204 spin_unlock_irqrestore(&device_domain_lock, flags);
Jiang Liufb170fb2014-07-11 14:19:28 +08002205
Wei Yang5c365d12016-07-13 13:53:21 +00002206 return ret;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002207}
2208
Lu Baolu0ce4a852019-08-26 16:50:56 +08002209struct domain_context_mapping_data {
2210 struct dmar_domain *domain;
2211 struct intel_iommu *iommu;
2212 struct pasid_table *table;
2213};
2214
2215static int domain_context_mapping_cb(struct pci_dev *pdev,
2216 u16 alias, void *opaque)
2217{
2218 struct domain_context_mapping_data *data = opaque;
2219
2220 return domain_context_mapping_one(data->domain, data->iommu,
2221 data->table, PCI_BUS_NUM(alias),
2222 alias & 0xff);
2223}
2224
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002225static int
Joerg Roedel28ccce02015-07-21 14:45:31 +02002226domain_context_mapping(struct dmar_domain *domain, struct device *dev)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002227{
Lu Baolu0ce4a852019-08-26 16:50:56 +08002228 struct domain_context_mapping_data data;
Lu Baoluca6e3222018-12-10 09:59:02 +08002229 struct pasid_table *table;
David Woodhouse64ae8922014-03-09 12:52:30 -07002230 struct intel_iommu *iommu;
David Woodhouse156baca2014-03-09 14:00:57 -07002231 u8 bus, devfn;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002232
David Woodhousee1f167f2014-03-09 15:24:46 -07002233 iommu = device_to_iommu(dev, &bus, &devfn);
David Woodhouse64ae8922014-03-09 12:52:30 -07002234 if (!iommu)
2235 return -ENODEV;
2236
Lu Baoluca6e3222018-12-10 09:59:02 +08002237 table = intel_pasid_get_table(dev);
Lu Baolu0ce4a852019-08-26 16:50:56 +08002238
2239 if (!dev_is_pci(dev))
2240 return domain_context_mapping_one(domain, iommu, table,
2241 bus, devfn);
2242
2243 data.domain = domain;
2244 data.iommu = iommu;
2245 data.table = table;
2246
2247 return pci_for_each_dma_alias(to_pci_dev(dev),
2248 &domain_context_mapping_cb, &data);
Alex Williamson579305f2014-07-03 09:51:43 -06002249}
2250
2251static int domain_context_mapped_cb(struct pci_dev *pdev,
2252 u16 alias, void *opaque)
2253{
2254 struct intel_iommu *iommu = opaque;
2255
2256 return !device_context_mapped(iommu, PCI_BUS_NUM(alias), alias & 0xff);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002257}
2258
David Woodhousee1f167f2014-03-09 15:24:46 -07002259static int domain_context_mapped(struct device *dev)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002260{
Weidong Han5331fe62008-12-08 23:00:00 +08002261 struct intel_iommu *iommu;
David Woodhouse156baca2014-03-09 14:00:57 -07002262 u8 bus, devfn;
Weidong Han5331fe62008-12-08 23:00:00 +08002263
David Woodhousee1f167f2014-03-09 15:24:46 -07002264 iommu = device_to_iommu(dev, &bus, &devfn);
Weidong Han5331fe62008-12-08 23:00:00 +08002265 if (!iommu)
2266 return -ENODEV;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002267
Alex Williamson579305f2014-07-03 09:51:43 -06002268 if (!dev_is_pci(dev))
2269 return device_context_mapped(iommu, bus, devfn);
David Woodhousee1f167f2014-03-09 15:24:46 -07002270
Alex Williamson579305f2014-07-03 09:51:43 -06002271 return !pci_for_each_dma_alias(to_pci_dev(dev),
2272 domain_context_mapped_cb, iommu);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002273}
2274
Fenghua Yuf5329592009-08-04 15:09:37 -07002275/* Returns a number of VTD pages, but aligned to MM page size */
2276static inline unsigned long aligned_nrpages(unsigned long host_addr,
2277 size_t size)
2278{
2279 host_addr &= ~PAGE_MASK;
2280 return PAGE_ALIGN(host_addr + size) >> VTD_PAGE_SHIFT;
2281}
2282
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002283/* Return largest possible superpage level for a given mapping */
2284static inline int hardware_largepage_caps(struct dmar_domain *domain,
2285 unsigned long iov_pfn,
2286 unsigned long phy_pfn,
2287 unsigned long pages)
2288{
2289 int support, level = 1;
2290 unsigned long pfnmerge;
2291
2292 support = domain->iommu_superpage;
2293
2294 /* To use a large page, the virtual *and* physical addresses
2295 must be aligned to 2MiB/1GiB/etc. Lower bits set in either
2296 of them will mean we have to use smaller pages. So just
2297 merge them and check both at once. */
2298 pfnmerge = iov_pfn | phy_pfn;
2299
2300 while (support && !(pfnmerge & ~VTD_STRIDE_MASK)) {
2301 pages >>= VTD_STRIDE_SHIFT;
2302 if (!pages)
2303 break;
2304 pfnmerge >>= VTD_STRIDE_SHIFT;
2305 level++;
2306 support--;
2307 }
2308 return level;
2309}
2310
David Woodhouse9051aa02009-06-29 12:30:54 +01002311static int __domain_mapping(struct dmar_domain *domain, unsigned long iov_pfn,
2312 struct scatterlist *sg, unsigned long phys_pfn,
2313 unsigned long nr_pages, int prot)
David Woodhousee1605492009-06-29 11:17:38 +01002314{
2315 struct dma_pte *first_pte = NULL, *pte = NULL;
David Woodhouse9051aa02009-06-29 12:30:54 +01002316 phys_addr_t uninitialized_var(pteval);
Jiang Liucc4f14a2014-11-26 09:42:10 +08002317 unsigned long sg_res = 0;
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002318 unsigned int largepage_lvl = 0;
2319 unsigned long lvl_pages = 0;
Lu Baoluddf09b62020-01-02 08:18:17 +08002320 u64 attr;
David Woodhousee1605492009-06-29 11:17:38 +01002321
Jiang Liu162d1b12014-07-11 14:19:35 +08002322 BUG_ON(!domain_pfn_supported(domain, iov_pfn + nr_pages - 1));
David Woodhousee1605492009-06-29 11:17:38 +01002323
2324 if ((prot & (DMA_PTE_READ|DMA_PTE_WRITE)) == 0)
2325 return -EINVAL;
2326
Lu Baoluddf09b62020-01-02 08:18:17 +08002327 attr = prot & (DMA_PTE_READ | DMA_PTE_WRITE | DMA_PTE_SNP);
2328 if (domain_use_first_level(domain))
2329 attr |= DMA_FL_PTE_PRESENT | DMA_FL_PTE_XD;
David Woodhousee1605492009-06-29 11:17:38 +01002330
Jiang Liucc4f14a2014-11-26 09:42:10 +08002331 if (!sg) {
2332 sg_res = nr_pages;
Lu Baoluddf09b62020-01-02 08:18:17 +08002333 pteval = ((phys_addr_t)phys_pfn << VTD_PAGE_SHIFT) | attr;
David Woodhouse9051aa02009-06-29 12:30:54 +01002334 }
2335
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002336 while (nr_pages > 0) {
David Woodhousec85994e2009-07-01 19:21:24 +01002337 uint64_t tmp;
2338
David Woodhousee1605492009-06-29 11:17:38 +01002339 if (!sg_res) {
Robin Murphy29a90b72017-09-28 15:14:01 +01002340 unsigned int pgoff = sg->offset & ~PAGE_MASK;
2341
Fenghua Yuf5329592009-08-04 15:09:37 -07002342 sg_res = aligned_nrpages(sg->offset, sg->length);
Robin Murphy29a90b72017-09-28 15:14:01 +01002343 sg->dma_address = ((dma_addr_t)iov_pfn << VTD_PAGE_SHIFT) + pgoff;
David Woodhousee1605492009-06-29 11:17:38 +01002344 sg->dma_length = sg->length;
Lu Baoluddf09b62020-01-02 08:18:17 +08002345 pteval = (sg_phys(sg) - pgoff) | attr;
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002346 phys_pfn = pteval >> VTD_PAGE_SHIFT;
David Woodhousee1605492009-06-29 11:17:38 +01002347 }
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002348
David Woodhousee1605492009-06-29 11:17:38 +01002349 if (!pte) {
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002350 largepage_lvl = hardware_largepage_caps(domain, iov_pfn, phys_pfn, sg_res);
2351
David Woodhouse5cf0a762014-03-19 16:07:49 +00002352 first_pte = pte = pfn_to_dma_pte(domain, iov_pfn, &largepage_lvl);
David Woodhousee1605492009-06-29 11:17:38 +01002353 if (!pte)
2354 return -ENOMEM;
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002355 /* It is large page*/
Woodhouse, David6491d4d2012-12-19 13:25:35 +00002356 if (largepage_lvl > 1) {
Christian Zanderba2374f2015-06-10 09:41:45 -07002357 unsigned long nr_superpages, end_pfn;
2358
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002359 pteval |= DMA_PTE_LARGE_PAGE;
Jiang Liud41a4ad2014-07-11 14:19:34 +08002360 lvl_pages = lvl_to_nr_pages(largepage_lvl);
Christian Zanderba2374f2015-06-10 09:41:45 -07002361
2362 nr_superpages = sg_res / lvl_pages;
2363 end_pfn = iov_pfn + nr_superpages * lvl_pages - 1;
2364
Jiang Liud41a4ad2014-07-11 14:19:34 +08002365 /*
2366 * Ensure that old small page tables are
Christian Zanderba2374f2015-06-10 09:41:45 -07002367 * removed to make room for superpage(s).
David Dillowbc24c572017-06-28 19:42:23 -07002368 * We're adding new large pages, so make sure
2369 * we don't remove their parent tables.
Jiang Liud41a4ad2014-07-11 14:19:34 +08002370 */
David Dillowbc24c572017-06-28 19:42:23 -07002371 dma_pte_free_pagetable(domain, iov_pfn, end_pfn,
2372 largepage_lvl + 1);
Woodhouse, David6491d4d2012-12-19 13:25:35 +00002373 } else {
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002374 pteval &= ~(uint64_t)DMA_PTE_LARGE_PAGE;
Woodhouse, David6491d4d2012-12-19 13:25:35 +00002375 }
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002376
David Woodhousee1605492009-06-29 11:17:38 +01002377 }
2378 /* We don't need lock here, nobody else
2379 * touches the iova range
2380 */
David Woodhouse7766a3f2009-07-01 20:27:03 +01002381 tmp = cmpxchg64_local(&pte->val, 0ULL, pteval);
David Woodhousec85994e2009-07-01 19:21:24 +01002382 if (tmp) {
David Woodhouse1bf20f02009-06-29 22:06:43 +01002383 static int dumps = 5;
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02002384 pr_crit("ERROR: DMA PTE for vPFN 0x%lx already set (to %llx not %llx)\n",
2385 iov_pfn, tmp, (unsigned long long)pteval);
David Woodhouse1bf20f02009-06-29 22:06:43 +01002386 if (dumps) {
2387 dumps--;
2388 debug_dma_dump_mappings(NULL);
2389 }
2390 WARN_ON(1);
2391 }
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002392
2393 lvl_pages = lvl_to_nr_pages(largepage_lvl);
2394
2395 BUG_ON(nr_pages < lvl_pages);
2396 BUG_ON(sg_res < lvl_pages);
2397
2398 nr_pages -= lvl_pages;
2399 iov_pfn += lvl_pages;
2400 phys_pfn += lvl_pages;
2401 pteval += lvl_pages * VTD_PAGE_SIZE;
2402 sg_res -= lvl_pages;
2403
2404 /* If the next PTE would be the first in a new page, then we
2405 need to flush the cache on the entries we've just written.
2406 And then we'll need to recalculate 'pte', so clear it and
2407 let it get set again in the if (!pte) block above.
2408
2409 If we're done (!nr_pages) we need to flush the cache too.
2410
2411 Also if we've been setting superpages, we may need to
2412 recalculate 'pte' and switch back to smaller pages for the
2413 end of the mapping, if the trailing size is not enough to
2414 use another superpage (i.e. sg_res < lvl_pages). */
David Woodhousee1605492009-06-29 11:17:38 +01002415 pte++;
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002416 if (!nr_pages || first_pte_in_page(pte) ||
2417 (largepage_lvl > 1 && sg_res < lvl_pages)) {
David Woodhousee1605492009-06-29 11:17:38 +01002418 domain_flush_cache(domain, first_pte,
2419 (void *)pte - (void *)first_pte);
2420 pte = NULL;
2421 }
Youquan Song6dd9a7c2011-05-25 19:13:49 +01002422
2423 if (!sg_res && nr_pages)
David Woodhousee1605492009-06-29 11:17:38 +01002424 sg = sg_next(sg);
2425 }
2426 return 0;
2427}
2428
Peter Xu87684fd2018-05-04 10:34:53 +08002429static int domain_mapping(struct dmar_domain *domain, unsigned long iov_pfn,
Lu Baolu095303e2019-04-29 09:16:02 +08002430 struct scatterlist *sg, unsigned long phys_pfn,
2431 unsigned long nr_pages, int prot)
Peter Xu87684fd2018-05-04 10:34:53 +08002432{
Lu Baolufa954e62019-05-25 13:41:28 +08002433 int iommu_id, ret;
Lu Baolu095303e2019-04-29 09:16:02 +08002434 struct intel_iommu *iommu;
Peter Xu87684fd2018-05-04 10:34:53 +08002435
Lu Baolu095303e2019-04-29 09:16:02 +08002436 /* Do the real mapping first */
2437 ret = __domain_mapping(domain, iov_pfn, sg, phys_pfn, nr_pages, prot);
2438 if (ret)
2439 return ret;
Peter Xu87684fd2018-05-04 10:34:53 +08002440
Lu Baolufa954e62019-05-25 13:41:28 +08002441 for_each_domain_iommu(iommu_id, domain) {
2442 iommu = g_iommus[iommu_id];
Lu Baolu095303e2019-04-29 09:16:02 +08002443 __mapping_notify_one(iommu, domain, iov_pfn, nr_pages);
2444 }
2445
2446 return 0;
Peter Xu87684fd2018-05-04 10:34:53 +08002447}
2448
David Woodhouse9051aa02009-06-29 12:30:54 +01002449static inline int domain_sg_mapping(struct dmar_domain *domain, unsigned long iov_pfn,
2450 struct scatterlist *sg, unsigned long nr_pages,
2451 int prot)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002452{
Peter Xu87684fd2018-05-04 10:34:53 +08002453 return domain_mapping(domain, iov_pfn, sg, 0, nr_pages, prot);
David Woodhouse9051aa02009-06-29 12:30:54 +01002454}
Fenghua Yu5b6985c2008-10-16 18:02:32 -07002455
David Woodhouse9051aa02009-06-29 12:30:54 +01002456static inline int domain_pfn_mapping(struct dmar_domain *domain, unsigned long iov_pfn,
2457 unsigned long phys_pfn, unsigned long nr_pages,
2458 int prot)
2459{
Peter Xu87684fd2018-05-04 10:34:53 +08002460 return domain_mapping(domain, iov_pfn, NULL, phys_pfn, nr_pages, prot);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002461}
2462
Joerg Roedel2452d9d2015-07-23 16:20:14 +02002463static void domain_context_clear_one(struct intel_iommu *iommu, u8 bus, u8 devfn)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002464{
Filippo Sironi50822192017-08-31 10:58:11 +02002465 unsigned long flags;
2466 struct context_entry *context;
2467 u16 did_old;
2468
Weidong Hanc7151a82008-12-08 22:51:37 +08002469 if (!iommu)
2470 return;
Weidong Han8c11e792008-12-08 15:29:22 +08002471
Filippo Sironi50822192017-08-31 10:58:11 +02002472 spin_lock_irqsave(&iommu->lock, flags);
2473 context = iommu_context_addr(iommu, bus, devfn, 0);
2474 if (!context) {
2475 spin_unlock_irqrestore(&iommu->lock, flags);
2476 return;
2477 }
2478 did_old = context_domain_id(context);
2479 context_clear_entry(context);
2480 __iommu_flush_cache(iommu, context, sizeof(*context));
2481 spin_unlock_irqrestore(&iommu->lock, flags);
2482 iommu->flush.flush_context(iommu,
2483 did_old,
2484 (((u16)bus) << 8) | devfn,
2485 DMA_CCMD_MASK_NOBIT,
2486 DMA_CCMD_DEVICE_INVL);
2487 iommu->flush.flush_iotlb(iommu,
2488 did_old,
2489 0,
2490 0,
2491 DMA_TLB_DSI_FLUSH);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002492}
2493
David Woodhouse109b9b02012-05-25 17:43:02 +01002494static inline void unlink_domain_info(struct device_domain_info *info)
2495{
2496 assert_spin_locked(&device_domain_lock);
2497 list_del(&info->link);
2498 list_del(&info->global);
2499 if (info->dev)
David Woodhouse0bcb3e22014-03-06 17:12:03 +00002500 info->dev->archdata.iommu = NULL;
David Woodhouse109b9b02012-05-25 17:43:02 +01002501}
2502
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002503static void domain_remove_dev_info(struct dmar_domain *domain)
2504{
Yijing Wang3a74ca02014-05-20 20:37:47 +08002505 struct device_domain_info *info, *tmp;
Jiang Liufb170fb2014-07-11 14:19:28 +08002506 unsigned long flags;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002507
2508 spin_lock_irqsave(&device_domain_lock, flags);
Joerg Roedel76f45fe2015-07-21 18:25:11 +02002509 list_for_each_entry_safe(info, tmp, &domain->devices, link)
Joerg Roedel127c7612015-07-23 17:44:46 +02002510 __dmar_remove_one_dev_info(info);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002511 spin_unlock_irqrestore(&device_domain_lock, flags);
2512}
2513
Lu Baolue2726da2020-01-02 08:18:22 +08002514struct dmar_domain *find_domain(struct device *dev)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002515{
2516 struct device_domain_info *info;
2517
Joerg Roedel1d46159782020-02-17 17:12:37 +01002518 if (unlikely(attach_deferred(dev) || iommu_dummy(dev)))
Lu Baolu1ee0186b2019-09-21 15:06:44 +08002519 return NULL;
2520
Jon Derrick2b0140c2020-01-21 06:37:48 -07002521 if (dev_is_pci(dev))
2522 dev = &pci_real_dma_dev(to_pci_dev(dev))->dev;
2523
Lu Baolu1ee0186b2019-09-21 15:06:44 +08002524 /* No lock here, assumes no domain exit in normal case */
2525 info = dev->archdata.iommu;
2526 if (likely(info))
2527 return info->domain;
2528
2529 return NULL;
2530}
2531
Joerg Roedel034d98c2020-02-17 17:16:19 +01002532static void do_deferred_attach(struct device *dev)
2533{
2534 struct iommu_domain *domain;
2535
2536 dev->archdata.iommu = NULL;
2537 domain = iommu_get_domain_for_dev(dev);
2538 if (domain)
2539 intel_iommu_attach_device(domain, dev);
2540}
2541
David Woodhouse5a8f40e2014-03-09 13:31:18 -07002542static inline struct device_domain_info *
Jiang Liu745f2582014-02-19 14:07:26 +08002543dmar_search_domain_by_dev_info(int segment, int bus, int devfn)
2544{
2545 struct device_domain_info *info;
2546
2547 list_for_each_entry(info, &device_domain_list, global)
David Woodhouse41e80dca2014-03-09 13:55:54 -07002548 if (info->iommu->segment == segment && info->bus == bus &&
Jiang Liu745f2582014-02-19 14:07:26 +08002549 info->devfn == devfn)
David Woodhouse5a8f40e2014-03-09 13:31:18 -07002550 return info;
Jiang Liu745f2582014-02-19 14:07:26 +08002551
2552 return NULL;
2553}
2554
Lu Baoluddf09b62020-01-02 08:18:17 +08002555static int domain_setup_first_level(struct intel_iommu *iommu,
2556 struct dmar_domain *domain,
2557 struct device *dev,
2558 int pasid)
2559{
2560 int flags = PASID_FLAG_SUPERVISOR_MODE;
2561 struct dma_pte *pgd = domain->pgd;
2562 int agaw, level;
2563
2564 /*
2565 * Skip top levels of page tables for iommu which has
2566 * less agaw than default. Unnecessary for PT mode.
2567 */
2568 for (agaw = domain->agaw; agaw > iommu->agaw; agaw--) {
2569 pgd = phys_to_virt(dma_pte_addr(pgd));
2570 if (!dma_pte_present(pgd))
2571 return -ENOMEM;
2572 }
2573
2574 level = agaw_to_level(agaw);
2575 if (level != 4 && level != 5)
2576 return -EINVAL;
2577
2578 flags |= (level == 5) ? PASID_FLAG_FL5LP : 0;
2579
2580 return intel_pasid_setup_first_level(iommu, dev, (pgd_t *)pgd, pasid,
2581 domain->iommu_did[iommu->seq_id],
2582 flags);
2583}
2584
Joerg Roedel5db31562015-07-22 12:40:43 +02002585static struct dmar_domain *dmar_insert_one_dev_info(struct intel_iommu *iommu,
2586 int bus, int devfn,
2587 struct device *dev,
2588 struct dmar_domain *domain)
Jiang Liu745f2582014-02-19 14:07:26 +08002589{
David Woodhouse5a8f40e2014-03-09 13:31:18 -07002590 struct dmar_domain *found = NULL;
Jiang Liu745f2582014-02-19 14:07:26 +08002591 struct device_domain_info *info;
2592 unsigned long flags;
Joerg Roedeld160aca2015-07-22 11:52:53 +02002593 int ret;
Jiang Liu745f2582014-02-19 14:07:26 +08002594
2595 info = alloc_devinfo_mem();
2596 if (!info)
David Woodhouseb718cd32014-03-09 13:11:33 -07002597 return NULL;
Jiang Liu745f2582014-02-19 14:07:26 +08002598
Jiang Liu745f2582014-02-19 14:07:26 +08002599 info->bus = bus;
2600 info->devfn = devfn;
David Woodhouseb16d0cb2015-10-12 14:17:37 +01002601 info->ats_supported = info->pasid_supported = info->pri_supported = 0;
2602 info->ats_enabled = info->pasid_enabled = info->pri_enabled = 0;
2603 info->ats_qdep = 0;
Jiang Liu745f2582014-02-19 14:07:26 +08002604 info->dev = dev;
2605 info->domain = domain;
David Woodhouse5a8f40e2014-03-09 13:31:18 -07002606 info->iommu = iommu;
Lu Baolucc580e42018-07-14 15:46:59 +08002607 info->pasid_table = NULL;
Lu Baolu95587a72019-03-25 09:30:30 +08002608 info->auxd_enabled = 0;
Lu Baolu67b8e022019-03-25 09:30:32 +08002609 INIT_LIST_HEAD(&info->auxiliary_domains);
Jiang Liu745f2582014-02-19 14:07:26 +08002610
David Woodhouseb16d0cb2015-10-12 14:17:37 +01002611 if (dev && dev_is_pci(dev)) {
2612 struct pci_dev *pdev = to_pci_dev(info->dev);
2613
Lu Baolud8b85912019-03-01 11:23:10 +08002614 if (!pdev->untrusted &&
2615 !pci_ats_disabled() &&
Gil Kupfercef74402018-05-10 17:56:02 -05002616 ecap_dev_iotlb_support(iommu->ecap) &&
David Woodhouseb16d0cb2015-10-12 14:17:37 +01002617 pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ATS) &&
2618 dmar_find_matched_atsr_unit(pdev))
2619 info->ats_supported = 1;
2620
Lu Baolu765b6a92018-12-10 09:58:55 +08002621 if (sm_supported(iommu)) {
2622 if (pasid_supported(iommu)) {
David Woodhouseb16d0cb2015-10-12 14:17:37 +01002623 int features = pci_pasid_features(pdev);
2624 if (features >= 0)
2625 info->pasid_supported = features | 1;
2626 }
2627
2628 if (info->ats_supported && ecap_prs(iommu->ecap) &&
2629 pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_PRI))
2630 info->pri_supported = 1;
2631 }
2632 }
2633
Jiang Liu745f2582014-02-19 14:07:26 +08002634 spin_lock_irqsave(&device_domain_lock, flags);
2635 if (dev)
David Woodhouse0bcb3e22014-03-06 17:12:03 +00002636 found = find_domain(dev);
Joerg Roedelf303e502015-07-23 18:37:13 +02002637
2638 if (!found) {
David Woodhouse5a8f40e2014-03-09 13:31:18 -07002639 struct device_domain_info *info2;
David Woodhouse41e80dca2014-03-09 13:55:54 -07002640 info2 = dmar_search_domain_by_dev_info(iommu->segment, bus, devfn);
Joerg Roedelf303e502015-07-23 18:37:13 +02002641 if (info2) {
2642 found = info2->domain;
2643 info2->dev = dev;
2644 }
David Woodhouse5a8f40e2014-03-09 13:31:18 -07002645 }
Joerg Roedelf303e502015-07-23 18:37:13 +02002646
Jiang Liu745f2582014-02-19 14:07:26 +08002647 if (found) {
2648 spin_unlock_irqrestore(&device_domain_lock, flags);
2649 free_devinfo_mem(info);
David Woodhouseb718cd32014-03-09 13:11:33 -07002650 /* Caller must free the original domain */
2651 return found;
Jiang Liu745f2582014-02-19 14:07:26 +08002652 }
2653
Joerg Roedeld160aca2015-07-22 11:52:53 +02002654 spin_lock(&iommu->lock);
2655 ret = domain_attach_iommu(domain, iommu);
2656 spin_unlock(&iommu->lock);
2657
2658 if (ret) {
Joerg Roedelc6c2ceb2015-07-22 13:11:53 +02002659 spin_unlock_irqrestore(&device_domain_lock, flags);
Sudip Mukherjee499f3aa2015-09-18 16:27:07 +05302660 free_devinfo_mem(info);
Joerg Roedelc6c2ceb2015-07-22 13:11:53 +02002661 return NULL;
2662 }
Joerg Roedelc6c2ceb2015-07-22 13:11:53 +02002663
David Woodhouseb718cd32014-03-09 13:11:33 -07002664 list_add(&info->link, &domain->devices);
2665 list_add(&info->global, &device_domain_list);
2666 if (dev)
2667 dev->archdata.iommu = info;
Lu Baolu0bbeb012018-12-10 09:58:56 +08002668 spin_unlock_irqrestore(&device_domain_lock, flags);
Lu Baolua7fc93f2018-07-14 15:47:00 +08002669
Lu Baolu0bbeb012018-12-10 09:58:56 +08002670 /* PASID table is mandatory for a PCI device in scalable mode. */
2671 if (dev && dev_is_pci(dev) && sm_supported(iommu)) {
Lu Baolua7fc93f2018-07-14 15:47:00 +08002672 ret = intel_pasid_alloc_table(dev);
2673 if (ret) {
Bjorn Helgaas932a6522019-02-08 16:06:00 -06002674 dev_err(dev, "PASID table allocation failed\n");
Bjorn Helgaas71753232019-02-08 16:06:15 -06002675 dmar_remove_one_dev_info(dev);
Lu Baolu0bbeb012018-12-10 09:58:56 +08002676 return NULL;
Lu Baolua7fc93f2018-07-14 15:47:00 +08002677 }
Lu Baoluef848b72018-12-10 09:59:01 +08002678
2679 /* Setup the PASID entry for requests without PASID: */
2680 spin_lock(&iommu->lock);
2681 if (hw_pass_through && domain_type_is_si(domain))
2682 ret = intel_pasid_setup_pass_through(iommu, domain,
2683 dev, PASID_RID2PASID);
Lu Baoluddf09b62020-01-02 08:18:17 +08002684 else if (domain_use_first_level(domain))
2685 ret = domain_setup_first_level(iommu, domain, dev,
2686 PASID_RID2PASID);
Lu Baoluef848b72018-12-10 09:59:01 +08002687 else
2688 ret = intel_pasid_setup_second_level(iommu, domain,
2689 dev, PASID_RID2PASID);
2690 spin_unlock(&iommu->lock);
2691 if (ret) {
Bjorn Helgaas932a6522019-02-08 16:06:00 -06002692 dev_err(dev, "Setup RID2PASID failed\n");
Bjorn Helgaas71753232019-02-08 16:06:15 -06002693 dmar_remove_one_dev_info(dev);
Lu Baoluef848b72018-12-10 09:59:01 +08002694 return NULL;
Lu Baolua7fc93f2018-07-14 15:47:00 +08002695 }
2696 }
David Woodhouseb718cd32014-03-09 13:11:33 -07002697
Joerg Roedelcc4e2572015-07-22 10:04:36 +02002698 if (dev && domain_context_mapping(domain, dev)) {
Bjorn Helgaas932a6522019-02-08 16:06:00 -06002699 dev_err(dev, "Domain context map failed\n");
Bjorn Helgaas71753232019-02-08 16:06:15 -06002700 dmar_remove_one_dev_info(dev);
Joerg Roedelcc4e2572015-07-22 10:04:36 +02002701 return NULL;
2702 }
2703
David Woodhouseb718cd32014-03-09 13:11:33 -07002704 return domain;
Jiang Liu745f2582014-02-19 14:07:26 +08002705}
2706
Alex Williamson579305f2014-07-03 09:51:43 -06002707static int get_last_alias(struct pci_dev *pdev, u16 alias, void *opaque)
2708{
2709 *(u16 *)opaque = alias;
2710 return 0;
2711}
2712
Joerg Roedel76208352016-08-25 14:25:12 +02002713static struct dmar_domain *find_or_alloc_domain(struct device *dev, int gaw)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002714{
Bjorn Helgaase083ea5b2019-02-08 16:06:08 -06002715 struct device_domain_info *info;
Joerg Roedel76208352016-08-25 14:25:12 +02002716 struct dmar_domain *domain = NULL;
Alex Williamson579305f2014-07-03 09:51:43 -06002717 struct intel_iommu *iommu;
Lu Baolufcc35c62018-05-04 13:08:17 +08002718 u16 dma_alias;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002719 unsigned long flags;
Yijing Wangaa4d0662014-05-26 20:14:06 +08002720 u8 bus, devfn;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002721
David Woodhouse146922e2014-03-09 15:44:17 -07002722 iommu = device_to_iommu(dev, &bus, &devfn);
2723 if (!iommu)
Alex Williamson579305f2014-07-03 09:51:43 -06002724 return NULL;
2725
2726 if (dev_is_pci(dev)) {
2727 struct pci_dev *pdev = to_pci_dev(dev);
2728
2729 pci_for_each_dma_alias(pdev, get_last_alias, &dma_alias);
2730
2731 spin_lock_irqsave(&device_domain_lock, flags);
2732 info = dmar_search_domain_by_dev_info(pci_domain_nr(pdev->bus),
2733 PCI_BUS_NUM(dma_alias),
2734 dma_alias & 0xff);
2735 if (info) {
2736 iommu = info->iommu;
2737 domain = info->domain;
2738 }
2739 spin_unlock_irqrestore(&device_domain_lock, flags);
2740
Joerg Roedel76208352016-08-25 14:25:12 +02002741 /* DMA alias already has a domain, use it */
Alex Williamson579305f2014-07-03 09:51:43 -06002742 if (info)
Joerg Roedel76208352016-08-25 14:25:12 +02002743 goto out;
Alex Williamson579305f2014-07-03 09:51:43 -06002744 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002745
David Woodhouse146922e2014-03-09 15:44:17 -07002746 /* Allocate and initialize new domain for the device */
Jiang Liuab8dfe22014-07-11 14:19:27 +08002747 domain = alloc_domain(0);
Jiang Liu745f2582014-02-19 14:07:26 +08002748 if (!domain)
Alex Williamson579305f2014-07-03 09:51:43 -06002749 return NULL;
Joerg Roedel301e7ee2019-07-22 16:21:05 +02002750 if (domain_init(domain, iommu, gaw)) {
Alex Williamson579305f2014-07-03 09:51:43 -06002751 domain_exit(domain);
2752 return NULL;
2753 }
2754
Joerg Roedel76208352016-08-25 14:25:12 +02002755out:
Joerg Roedel76208352016-08-25 14:25:12 +02002756 return domain;
2757}
2758
2759static struct dmar_domain *set_domain_for_dev(struct device *dev,
2760 struct dmar_domain *domain)
2761{
2762 struct intel_iommu *iommu;
2763 struct dmar_domain *tmp;
2764 u16 req_id, dma_alias;
2765 u8 bus, devfn;
2766
2767 iommu = device_to_iommu(dev, &bus, &devfn);
2768 if (!iommu)
2769 return NULL;
2770
2771 req_id = ((u16)bus << 8) | devfn;
2772
2773 if (dev_is_pci(dev)) {
2774 struct pci_dev *pdev = to_pci_dev(dev);
2775
2776 pci_for_each_dma_alias(pdev, get_last_alias, &dma_alias);
2777
2778 /* register PCI DMA alias device */
2779 if (req_id != dma_alias) {
2780 tmp = dmar_insert_one_dev_info(iommu, PCI_BUS_NUM(dma_alias),
2781 dma_alias & 0xff, NULL, domain);
2782
2783 if (!tmp || tmp != domain)
2784 return tmp;
Alex Williamson579305f2014-07-03 09:51:43 -06002785 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002786 }
2787
Joerg Roedel5db31562015-07-22 12:40:43 +02002788 tmp = dmar_insert_one_dev_info(iommu, bus, devfn, dev, domain);
Joerg Roedel76208352016-08-25 14:25:12 +02002789 if (!tmp || tmp != domain)
2790 return tmp;
Alex Williamson579305f2014-07-03 09:51:43 -06002791
Joerg Roedel76208352016-08-25 14:25:12 +02002792 return domain;
2793}
2794
David Woodhouseb2132032009-06-26 18:50:28 +01002795static int iommu_domain_identity_map(struct dmar_domain *domain,
2796 unsigned long long start,
2797 unsigned long long end)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002798{
David Woodhousec5395d52009-06-28 16:35:56 +01002799 unsigned long first_vpfn = start >> VTD_PAGE_SHIFT;
2800 unsigned long last_vpfn = end >> VTD_PAGE_SHIFT;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002801
David Woodhousec5395d52009-06-28 16:35:56 +01002802 if (!reserve_iova(&domain->iovad, dma_to_mm_pfn(first_vpfn),
2803 dma_to_mm_pfn(last_vpfn))) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02002804 pr_err("Reserving iova failed\n");
David Woodhouseb2132032009-06-26 18:50:28 +01002805 return -ENOMEM;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002806 }
2807
Joerg Roedelaf1089c2015-07-21 15:45:19 +02002808 pr_debug("Mapping reserved region %llx-%llx\n", start, end);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002809 /*
2810 * RMRR range might have overlap with physical memory range,
2811 * clear it first
2812 */
David Woodhousec5395d52009-06-28 16:35:56 +01002813 dma_pte_clear_range(domain, first_vpfn, last_vpfn);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07002814
Peter Xu87684fd2018-05-04 10:34:53 +08002815 return __domain_mapping(domain, first_vpfn, NULL,
2816 first_vpfn, last_vpfn - first_vpfn + 1,
2817 DMA_PTE_READ|DMA_PTE_WRITE);
David Woodhouseb2132032009-06-26 18:50:28 +01002818}
2819
Joerg Roedeld66ce542015-09-23 19:00:10 +02002820static int domain_prepare_identity_map(struct device *dev,
2821 struct dmar_domain *domain,
2822 unsigned long long start,
2823 unsigned long long end)
David Woodhouseb2132032009-06-26 18:50:28 +01002824{
David Woodhouse19943b02009-08-04 16:19:20 +01002825 /* For _hardware_ passthrough, don't bother. But for software
2826 passthrough, we do it anyway -- it may indicate a memory
2827 range which is reserved in E820, so which didn't get set
2828 up to start with in si_domain */
2829 if (domain == si_domain && hw_pass_through) {
Bjorn Helgaas932a6522019-02-08 16:06:00 -06002830 dev_warn(dev, "Ignoring identity map for HW passthrough [0x%Lx - 0x%Lx]\n",
2831 start, end);
David Woodhouse19943b02009-08-04 16:19:20 +01002832 return 0;
2833 }
2834
Bjorn Helgaas932a6522019-02-08 16:06:00 -06002835 dev_info(dev, "Setting identity map [0x%Lx - 0x%Lx]\n", start, end);
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02002836
David Woodhouse5595b522009-12-02 09:21:55 +00002837 if (end < start) {
2838 WARN(1, "Your BIOS is broken; RMRR ends before it starts!\n"
2839 "BIOS vendor: %s; Ver: %s; Product Version: %s\n",
2840 dmi_get_system_info(DMI_BIOS_VENDOR),
2841 dmi_get_system_info(DMI_BIOS_VERSION),
2842 dmi_get_system_info(DMI_PRODUCT_VERSION));
Joerg Roedeld66ce542015-09-23 19:00:10 +02002843 return -EIO;
David Woodhouse5595b522009-12-02 09:21:55 +00002844 }
2845
David Woodhouse2ff729f2009-08-26 14:25:41 +01002846 if (end >> agaw_to_width(domain->agaw)) {
2847 WARN(1, "Your BIOS is broken; RMRR exceeds permitted address width (%d bits)\n"
2848 "BIOS vendor: %s; Ver: %s; Product Version: %s\n",
2849 agaw_to_width(domain->agaw),
2850 dmi_get_system_info(DMI_BIOS_VENDOR),
2851 dmi_get_system_info(DMI_BIOS_VERSION),
2852 dmi_get_system_info(DMI_PRODUCT_VERSION));
Joerg Roedeld66ce542015-09-23 19:00:10 +02002853 return -EIO;
David Woodhouse2ff729f2009-08-26 14:25:41 +01002854 }
David Woodhouse19943b02009-08-04 16:19:20 +01002855
Joerg Roedeld66ce542015-09-23 19:00:10 +02002856 return iommu_domain_identity_map(domain, start, end);
2857}
2858
Joerg Roedel301e7ee2019-07-22 16:21:05 +02002859static int md_domain_init(struct dmar_domain *domain, int guest_width);
2860
Matt Kraai071e1372009-08-23 22:30:22 -07002861static int __init si_domain_init(int hw)
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002862{
Lu Baolu4de354e2019-05-25 13:41:27 +08002863 struct dmar_rmrr_unit *rmrr;
2864 struct device *dev;
2865 int i, nid, ret;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002866
Jiang Liuab8dfe22014-07-11 14:19:27 +08002867 si_domain = alloc_domain(DOMAIN_FLAG_STATIC_IDENTITY);
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002868 if (!si_domain)
2869 return -EFAULT;
2870
Joerg Roedel301e7ee2019-07-22 16:21:05 +02002871 if (md_domain_init(si_domain, DEFAULT_DOMAIN_ADDRESS_WIDTH)) {
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002872 domain_exit(si_domain);
2873 return -EFAULT;
2874 }
2875
David Woodhouse19943b02009-08-04 16:19:20 +01002876 if (hw)
2877 return 0;
2878
David Woodhousec7ab48d2009-06-26 19:10:36 +01002879 for_each_online_node(nid) {
Tejun Heod4bbf7e2011-11-28 09:46:22 -08002880 unsigned long start_pfn, end_pfn;
2881 int i;
2882
2883 for_each_mem_pfn_range(i, nid, &start_pfn, &end_pfn, NULL) {
2884 ret = iommu_domain_identity_map(si_domain,
2885 PFN_PHYS(start_pfn), PFN_PHYS(end_pfn));
2886 if (ret)
2887 return ret;
2888 }
David Woodhousec7ab48d2009-06-26 19:10:36 +01002889 }
2890
Lu Baolu4de354e2019-05-25 13:41:27 +08002891 /*
Lu Baolu9235cb132020-01-15 11:03:58 +08002892 * Identity map the RMRRs so that devices with RMRRs could also use
2893 * the si_domain.
Lu Baolu4de354e2019-05-25 13:41:27 +08002894 */
2895 for_each_rmrr_units(rmrr) {
2896 for_each_active_dev_scope(rmrr->devices, rmrr->devices_cnt,
2897 i, dev) {
2898 unsigned long long start = rmrr->base_address;
2899 unsigned long long end = rmrr->end_address;
2900
Lu Baolu4de354e2019-05-25 13:41:27 +08002901 if (WARN_ON(end < start ||
2902 end >> agaw_to_width(si_domain->agaw)))
2903 continue;
2904
2905 ret = iommu_domain_identity_map(si_domain, start, end);
2906 if (ret)
2907 return ret;
2908 }
2909 }
2910
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002911 return 0;
2912}
2913
David Woodhouse9b226622014-03-09 14:03:28 -07002914static int identity_mapping(struct device *dev)
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002915{
2916 struct device_domain_info *info;
2917
David Woodhouse9b226622014-03-09 14:03:28 -07002918 info = dev->archdata.iommu;
Joerg Roedel1ddb32d2020-02-17 17:29:55 +01002919 if (info)
Mike Traviscb452a42011-05-28 13:15:03 -05002920 return (info->domain == si_domain);
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002921
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002922 return 0;
2923}
2924
Joerg Roedel28ccce02015-07-21 14:45:31 +02002925static int domain_add_dev_info(struct dmar_domain *domain, struct device *dev)
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002926{
David Woodhouse0ac72662014-03-09 13:19:22 -07002927 struct dmar_domain *ndomain;
David Woodhouse5a8f40e2014-03-09 13:31:18 -07002928 struct intel_iommu *iommu;
David Woodhouse156baca2014-03-09 14:00:57 -07002929 u8 bus, devfn;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002930
David Woodhouse5913c9b2014-03-09 16:27:31 -07002931 iommu = device_to_iommu(dev, &bus, &devfn);
David Woodhouse5a8f40e2014-03-09 13:31:18 -07002932 if (!iommu)
2933 return -ENODEV;
2934
Joerg Roedel5db31562015-07-22 12:40:43 +02002935 ndomain = dmar_insert_one_dev_info(iommu, bus, devfn, dev, domain);
David Woodhouse0ac72662014-03-09 13:19:22 -07002936 if (ndomain != domain)
2937 return -EBUSY;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07002938
2939 return 0;
2940}
2941
David Woodhouse0b9d9752014-03-09 15:48:15 -07002942static bool device_has_rmrr(struct device *dev)
Tom Mingarelliea2447f72012-11-20 19:43:17 +00002943{
2944 struct dmar_rmrr_unit *rmrr;
David Woodhouse832bd852014-03-07 15:08:36 +00002945 struct device *tmp;
Tom Mingarelliea2447f72012-11-20 19:43:17 +00002946 int i;
2947
Jiang Liu0e242612014-02-19 14:07:34 +08002948 rcu_read_lock();
Tom Mingarelliea2447f72012-11-20 19:43:17 +00002949 for_each_rmrr_units(rmrr) {
Jiang Liub683b232014-02-19 14:07:32 +08002950 /*
2951 * Return TRUE if this RMRR contains the device that
2952 * is passed in.
2953 */
2954 for_each_active_dev_scope(rmrr->devices,
2955 rmrr->devices_cnt, i, tmp)
Eric Augere143fd42019-06-03 08:53:33 +02002956 if (tmp == dev ||
2957 is_downstream_to_pci_bridge(dev, tmp)) {
Jiang Liu0e242612014-02-19 14:07:34 +08002958 rcu_read_unlock();
Tom Mingarelliea2447f72012-11-20 19:43:17 +00002959 return true;
Jiang Liub683b232014-02-19 14:07:32 +08002960 }
Tom Mingarelliea2447f72012-11-20 19:43:17 +00002961 }
Jiang Liu0e242612014-02-19 14:07:34 +08002962 rcu_read_unlock();
Tom Mingarelliea2447f72012-11-20 19:43:17 +00002963 return false;
2964}
2965
Eric Auger1c5c59f2019-06-03 08:53:36 +02002966/**
2967 * device_rmrr_is_relaxable - Test whether the RMRR of this device
2968 * is relaxable (ie. is allowed to be not enforced under some conditions)
2969 * @dev: device handle
2970 *
2971 * We assume that PCI USB devices with RMRRs have them largely
2972 * for historical reasons and that the RMRR space is not actively used post
2973 * boot. This exclusion may change if vendors begin to abuse it.
2974 *
2975 * The same exception is made for graphics devices, with the requirement that
2976 * any use of the RMRR regions will be torn down before assigning the device
2977 * to a guest.
2978 *
2979 * Return: true if the RMRR is relaxable, false otherwise
2980 */
2981static bool device_rmrr_is_relaxable(struct device *dev)
2982{
2983 struct pci_dev *pdev;
2984
2985 if (!dev_is_pci(dev))
2986 return false;
2987
2988 pdev = to_pci_dev(dev);
2989 if (IS_USB_DEVICE(pdev) || IS_GFX_DEVICE(pdev))
2990 return true;
2991 else
2992 return false;
2993}
2994
Alex Williamsonc875d2c2014-07-03 09:57:02 -06002995/*
2996 * There are a couple cases where we need to restrict the functionality of
2997 * devices associated with RMRRs. The first is when evaluating a device for
2998 * identity mapping because problems exist when devices are moved in and out
2999 * of domains and their respective RMRR information is lost. This means that
3000 * a device with associated RMRRs will never be in a "passthrough" domain.
3001 * The second is use of the device through the IOMMU API. This interface
3002 * expects to have full control of the IOVA space for the device. We cannot
3003 * satisfy both the requirement that RMRR access is maintained and have an
3004 * unencumbered IOVA space. We also have no ability to quiesce the device's
3005 * use of the RMRR space or even inform the IOMMU API user of the restriction.
3006 * We therefore prevent devices associated with an RMRR from participating in
3007 * the IOMMU API, which eliminates them from device assignment.
3008 *
Eric Auger1c5c59f2019-06-03 08:53:36 +02003009 * In both cases, devices which have relaxable RMRRs are not concerned by this
3010 * restriction. See device_rmrr_is_relaxable comment.
Alex Williamsonc875d2c2014-07-03 09:57:02 -06003011 */
3012static bool device_is_rmrr_locked(struct device *dev)
3013{
3014 if (!device_has_rmrr(dev))
3015 return false;
3016
Eric Auger1c5c59f2019-06-03 08:53:36 +02003017 if (device_rmrr_is_relaxable(dev))
3018 return false;
Alex Williamsonc875d2c2014-07-03 09:57:02 -06003019
3020 return true;
3021}
3022
Lu Baoluf273a452019-05-25 13:41:26 +08003023/*
3024 * Return the required default domain type for a specific device.
3025 *
3026 * @dev: the device in query
3027 * @startup: true if this is during early boot
3028 *
3029 * Returns:
3030 * - IOMMU_DOMAIN_DMA: device requires a dynamic mapping domain
3031 * - IOMMU_DOMAIN_IDENTITY: device requires an identical mapping domain
3032 * - 0: both identity and dynamic domains work for this device
3033 */
Lu Baolu0e31a722019-05-25 13:41:34 +08003034static int device_def_domain_type(struct device *dev)
David Woodhouse6941af22009-07-04 18:24:27 +01003035{
David Woodhouse3bdb2592014-03-09 16:03:08 -07003036 if (dev_is_pci(dev)) {
3037 struct pci_dev *pdev = to_pci_dev(dev);
Tom Mingarelliea2447f72012-11-20 19:43:17 +00003038
Lu Baolu89a60792018-10-23 15:45:01 +08003039 /*
3040 * Prevent any device marked as untrusted from getting
3041 * placed into the statically identity mapping domain.
3042 */
3043 if (pdev->untrusted)
Lu Baoluf273a452019-05-25 13:41:26 +08003044 return IOMMU_DOMAIN_DMA;
Lu Baolu89a60792018-10-23 15:45:01 +08003045
David Woodhouse3bdb2592014-03-09 16:03:08 -07003046 if ((iommu_identity_mapping & IDENTMAP_AZALIA) && IS_AZALIA(pdev))
Lu Baoluf273a452019-05-25 13:41:26 +08003047 return IOMMU_DOMAIN_IDENTITY;
David Woodhousee0fc7e02009-09-30 09:12:17 -07003048
David Woodhouse3bdb2592014-03-09 16:03:08 -07003049 if ((iommu_identity_mapping & IDENTMAP_GFX) && IS_GFX_DEVICE(pdev))
Lu Baoluf273a452019-05-25 13:41:26 +08003050 return IOMMU_DOMAIN_IDENTITY;
David Woodhouse3bdb2592014-03-09 16:03:08 -07003051
3052 /*
3053 * We want to start off with all devices in the 1:1 domain, and
3054 * take them out later if we find they can't access all of memory.
3055 *
3056 * However, we can't do this for PCI devices behind bridges,
3057 * because all PCI devices behind the same bridge will end up
3058 * with the same source-id on their transactions.
3059 *
3060 * Practically speaking, we can't change things around for these
3061 * devices at run-time, because we can't be sure there'll be no
3062 * DMA transactions in flight for any of their siblings.
3063 *
3064 * So PCI devices (unless they're on the root bus) as well as
3065 * their parent PCI-PCI or PCIe-PCI bridges must be left _out_ of
3066 * the 1:1 domain, just in _case_ one of their siblings turns out
3067 * not to be able to map all of memory.
3068 */
3069 if (!pci_is_pcie(pdev)) {
3070 if (!pci_is_root_bus(pdev->bus))
Lu Baoluf273a452019-05-25 13:41:26 +08003071 return IOMMU_DOMAIN_DMA;
David Woodhouse3bdb2592014-03-09 16:03:08 -07003072 if (pdev->class >> 8 == PCI_CLASS_BRIDGE_PCI)
Lu Baoluf273a452019-05-25 13:41:26 +08003073 return IOMMU_DOMAIN_DMA;
David Woodhouse3bdb2592014-03-09 16:03:08 -07003074 } else if (pci_pcie_type(pdev) == PCI_EXP_TYPE_PCI_BRIDGE)
Lu Baoluf273a452019-05-25 13:41:26 +08003075 return IOMMU_DOMAIN_DMA;
David Woodhouse3bdb2592014-03-09 16:03:08 -07003076 }
David Woodhouse6941af22009-07-04 18:24:27 +01003077
Lu Baolub89b6602020-01-15 11:03:59 +08003078 return 0;
Lu Baoluf273a452019-05-25 13:41:26 +08003079}
3080
Jiang Liuffebeb42014-11-09 22:48:02 +08003081static void intel_iommu_init_qi(struct intel_iommu *iommu)
3082{
3083 /*
3084 * Start from the sane iommu hardware state.
3085 * If the queued invalidation is already initialized by us
3086 * (for example, while enabling interrupt-remapping) then
3087 * we got the things already rolling from a sane state.
3088 */
3089 if (!iommu->qi) {
3090 /*
3091 * Clear any previous faults.
3092 */
3093 dmar_fault(-1, iommu);
3094 /*
3095 * Disable queued invalidation if supported and already enabled
3096 * before OS handover.
3097 */
3098 dmar_disable_qi(iommu);
3099 }
3100
3101 if (dmar_enable_qi(iommu)) {
3102 /*
3103 * Queued Invalidate not enabled, use Register Based Invalidate
3104 */
3105 iommu->flush.flush_context = __iommu_flush_context;
3106 iommu->flush.flush_iotlb = __iommu_flush_iotlb;
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02003107 pr_info("%s: Using Register based invalidation\n",
Jiang Liuffebeb42014-11-09 22:48:02 +08003108 iommu->name);
3109 } else {
3110 iommu->flush.flush_context = qi_flush_context;
3111 iommu->flush.flush_iotlb = qi_flush_iotlb;
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02003112 pr_info("%s: Using Queued invalidation\n", iommu->name);
Jiang Liuffebeb42014-11-09 22:48:02 +08003113 }
3114}
3115
Joerg Roedel091d42e2015-06-12 11:56:10 +02003116static int copy_context_table(struct intel_iommu *iommu,
Dan Williamsdfddb962015-10-09 18:16:46 -04003117 struct root_entry *old_re,
Joerg Roedel091d42e2015-06-12 11:56:10 +02003118 struct context_entry **tbl,
3119 int bus, bool ext)
3120{
Joerg Roedeldbcd8612015-06-12 12:02:09 +02003121 int tbl_idx, pos = 0, idx, devfn, ret = 0, did;
Joerg Roedel543c8dc2015-08-13 11:56:59 +02003122 struct context_entry *new_ce = NULL, ce;
Dan Williamsdfddb962015-10-09 18:16:46 -04003123 struct context_entry *old_ce = NULL;
Joerg Roedel543c8dc2015-08-13 11:56:59 +02003124 struct root_entry re;
Joerg Roedel091d42e2015-06-12 11:56:10 +02003125 phys_addr_t old_ce_phys;
3126
3127 tbl_idx = ext ? bus * 2 : bus;
Dan Williamsdfddb962015-10-09 18:16:46 -04003128 memcpy(&re, old_re, sizeof(re));
Joerg Roedel091d42e2015-06-12 11:56:10 +02003129
3130 for (devfn = 0; devfn < 256; devfn++) {
3131 /* First calculate the correct index */
3132 idx = (ext ? devfn * 2 : devfn) % 256;
3133
3134 if (idx == 0) {
3135 /* First save what we may have and clean up */
3136 if (new_ce) {
3137 tbl[tbl_idx] = new_ce;
3138 __iommu_flush_cache(iommu, new_ce,
3139 VTD_PAGE_SIZE);
3140 pos = 1;
3141 }
3142
3143 if (old_ce)
Pan Bian829383e2018-11-21 17:53:47 +08003144 memunmap(old_ce);
Joerg Roedel091d42e2015-06-12 11:56:10 +02003145
3146 ret = 0;
3147 if (devfn < 0x80)
Joerg Roedel543c8dc2015-08-13 11:56:59 +02003148 old_ce_phys = root_entry_lctp(&re);
Joerg Roedel091d42e2015-06-12 11:56:10 +02003149 else
Joerg Roedel543c8dc2015-08-13 11:56:59 +02003150 old_ce_phys = root_entry_uctp(&re);
Joerg Roedel091d42e2015-06-12 11:56:10 +02003151
3152 if (!old_ce_phys) {
3153 if (ext && devfn == 0) {
3154 /* No LCTP, try UCTP */
3155 devfn = 0x7f;
3156 continue;
3157 } else {
3158 goto out;
3159 }
3160 }
3161
3162 ret = -ENOMEM;
Dan Williamsdfddb962015-10-09 18:16:46 -04003163 old_ce = memremap(old_ce_phys, PAGE_SIZE,
3164 MEMREMAP_WB);
Joerg Roedel091d42e2015-06-12 11:56:10 +02003165 if (!old_ce)
3166 goto out;
3167
3168 new_ce = alloc_pgtable_page(iommu->node);
3169 if (!new_ce)
3170 goto out_unmap;
3171
3172 ret = 0;
3173 }
3174
3175 /* Now copy the context entry */
Dan Williamsdfddb962015-10-09 18:16:46 -04003176 memcpy(&ce, old_ce + idx, sizeof(ce));
Joerg Roedel091d42e2015-06-12 11:56:10 +02003177
Joerg Roedelcf484d02015-06-12 12:21:46 +02003178 if (!__context_present(&ce))
Joerg Roedel091d42e2015-06-12 11:56:10 +02003179 continue;
3180
Joerg Roedeldbcd8612015-06-12 12:02:09 +02003181 did = context_domain_id(&ce);
3182 if (did >= 0 && did < cap_ndoms(iommu->cap))
3183 set_bit(did, iommu->domain_ids);
3184
Joerg Roedelcf484d02015-06-12 12:21:46 +02003185 /*
3186 * We need a marker for copied context entries. This
3187 * marker needs to work for the old format as well as
3188 * for extended context entries.
3189 *
3190 * Bit 67 of the context entry is used. In the old
3191 * format this bit is available to software, in the
3192 * extended format it is the PGE bit, but PGE is ignored
3193 * by HW if PASIDs are disabled (and thus still
3194 * available).
3195 *
3196 * So disable PASIDs first and then mark the entry
3197 * copied. This means that we don't copy PASID
3198 * translations from the old kernel, but this is fine as
3199 * faults there are not fatal.
3200 */
3201 context_clear_pasid_enable(&ce);
3202 context_set_copied(&ce);
3203
Joerg Roedel091d42e2015-06-12 11:56:10 +02003204 new_ce[idx] = ce;
3205 }
3206
3207 tbl[tbl_idx + pos] = new_ce;
3208
3209 __iommu_flush_cache(iommu, new_ce, VTD_PAGE_SIZE);
3210
3211out_unmap:
Dan Williamsdfddb962015-10-09 18:16:46 -04003212 memunmap(old_ce);
Joerg Roedel091d42e2015-06-12 11:56:10 +02003213
3214out:
3215 return ret;
3216}
3217
3218static int copy_translation_tables(struct intel_iommu *iommu)
3219{
3220 struct context_entry **ctxt_tbls;
Dan Williamsdfddb962015-10-09 18:16:46 -04003221 struct root_entry *old_rt;
Joerg Roedel091d42e2015-06-12 11:56:10 +02003222 phys_addr_t old_rt_phys;
3223 int ctxt_table_entries;
3224 unsigned long flags;
3225 u64 rtaddr_reg;
3226 int bus, ret;
Joerg Roedelc3361f22015-06-12 12:39:25 +02003227 bool new_ext, ext;
Joerg Roedel091d42e2015-06-12 11:56:10 +02003228
3229 rtaddr_reg = dmar_readq(iommu->reg + DMAR_RTADDR_REG);
3230 ext = !!(rtaddr_reg & DMA_RTADDR_RTT);
Joerg Roedelc3361f22015-06-12 12:39:25 +02003231 new_ext = !!ecap_ecs(iommu->ecap);
3232
3233 /*
3234 * The RTT bit can only be changed when translation is disabled,
3235 * but disabling translation means to open a window for data
3236 * corruption. So bail out and don't copy anything if we would
3237 * have to change the bit.
3238 */
3239 if (new_ext != ext)
3240 return -EINVAL;
Joerg Roedel091d42e2015-06-12 11:56:10 +02003241
3242 old_rt_phys = rtaddr_reg & VTD_PAGE_MASK;
3243 if (!old_rt_phys)
3244 return -EINVAL;
3245
Dan Williamsdfddb962015-10-09 18:16:46 -04003246 old_rt = memremap(old_rt_phys, PAGE_SIZE, MEMREMAP_WB);
Joerg Roedel091d42e2015-06-12 11:56:10 +02003247 if (!old_rt)
3248 return -ENOMEM;
3249
3250 /* This is too big for the stack - allocate it from slab */
3251 ctxt_table_entries = ext ? 512 : 256;
3252 ret = -ENOMEM;
Kees Cook6396bb22018-06-12 14:03:40 -07003253 ctxt_tbls = kcalloc(ctxt_table_entries, sizeof(void *), GFP_KERNEL);
Joerg Roedel091d42e2015-06-12 11:56:10 +02003254 if (!ctxt_tbls)
3255 goto out_unmap;
3256
3257 for (bus = 0; bus < 256; bus++) {
3258 ret = copy_context_table(iommu, &old_rt[bus],
3259 ctxt_tbls, bus, ext);
3260 if (ret) {
3261 pr_err("%s: Failed to copy context table for bus %d\n",
3262 iommu->name, bus);
3263 continue;
3264 }
3265 }
3266
3267 spin_lock_irqsave(&iommu->lock, flags);
3268
3269 /* Context tables are copied, now write them to the root_entry table */
3270 for (bus = 0; bus < 256; bus++) {
3271 int idx = ext ? bus * 2 : bus;
3272 u64 val;
3273
3274 if (ctxt_tbls[idx]) {
3275 val = virt_to_phys(ctxt_tbls[idx]) | 1;
3276 iommu->root_entry[bus].lo = val;
3277 }
3278
3279 if (!ext || !ctxt_tbls[idx + 1])
3280 continue;
3281
3282 val = virt_to_phys(ctxt_tbls[idx + 1]) | 1;
3283 iommu->root_entry[bus].hi = val;
3284 }
3285
3286 spin_unlock_irqrestore(&iommu->lock, flags);
3287
3288 kfree(ctxt_tbls);
3289
3290 __iommu_flush_cache(iommu, iommu->root_entry, PAGE_SIZE);
3291
3292 ret = 0;
3293
3294out_unmap:
Dan Williamsdfddb962015-10-09 18:16:46 -04003295 memunmap(old_rt);
Joerg Roedel091d42e2015-06-12 11:56:10 +02003296
3297 return ret;
3298}
3299
Joseph Cihulab7792602011-05-03 00:08:37 -07003300static int __init init_dmars(void)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003301{
3302 struct dmar_drhd_unit *drhd;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003303 struct intel_iommu *iommu;
Lu Baoludf4f3c62019-05-25 13:41:36 +08003304 int ret;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003305
3306 /*
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003307 * for each drhd
3308 * allocate root
3309 * initialize and program root entry to not present
3310 * endfor
3311 */
3312 for_each_drhd_unit(drhd) {
mark gross5e0d2a62008-03-04 15:22:08 -08003313 /*
3314 * lock not needed as this is only incremented in the single
3315 * threaded kernel __init code path all other access are read
3316 * only
3317 */
Jiang Liu78d8e702014-11-09 22:47:57 +08003318 if (g_num_of_iommus < DMAR_UNITS_SUPPORTED) {
Mike Travis1b198bb2012-03-05 15:05:16 -08003319 g_num_of_iommus++;
3320 continue;
3321 }
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02003322 pr_err_once("Exceeded %d IOMMUs\n", DMAR_UNITS_SUPPORTED);
mark gross5e0d2a62008-03-04 15:22:08 -08003323 }
3324
Jiang Liuffebeb42014-11-09 22:48:02 +08003325 /* Preallocate enough resources for IOMMU hot-addition */
3326 if (g_num_of_iommus < DMAR_UNITS_SUPPORTED)
3327 g_num_of_iommus = DMAR_UNITS_SUPPORTED;
3328
Weidong Hand9630fe2008-12-08 11:06:32 +08003329 g_iommus = kcalloc(g_num_of_iommus, sizeof(struct intel_iommu *),
3330 GFP_KERNEL);
3331 if (!g_iommus) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02003332 pr_err("Allocating global iommu array failed\n");
Weidong Hand9630fe2008-12-08 11:06:32 +08003333 ret = -ENOMEM;
3334 goto error;
3335 }
3336
Lu Baolu6a8c6742019-06-12 08:28:47 +08003337 for_each_iommu(iommu, drhd) {
3338 if (drhd->ignored) {
3339 iommu_disable_translation(iommu);
3340 continue;
3341 }
3342
Lu Baolu56283172018-07-14 15:46:54 +08003343 /*
3344 * Find the max pasid size of all IOMMU's in the system.
3345 * We need to ensure the system pasid table is no bigger
3346 * than the smallest supported.
3347 */
Lu Baolu765b6a92018-12-10 09:58:55 +08003348 if (pasid_supported(iommu)) {
Lu Baolu56283172018-07-14 15:46:54 +08003349 u32 temp = 2 << ecap_pss(iommu->ecap);
3350
3351 intel_pasid_max_id = min_t(u32, temp,
3352 intel_pasid_max_id);
3353 }
3354
Weidong Hand9630fe2008-12-08 11:06:32 +08003355 g_iommus[iommu->seq_id] = iommu;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003356
Joerg Roedelb63d80d2015-06-12 09:14:34 +02003357 intel_iommu_init_qi(iommu);
3358
Suresh Siddhae61d98d2008-07-10 11:16:35 -07003359 ret = iommu_init_domains(iommu);
3360 if (ret)
Jiang Liu989d51f2014-02-19 14:07:21 +08003361 goto free_iommu;
Suresh Siddhae61d98d2008-07-10 11:16:35 -07003362
Joerg Roedel4158c2e2015-06-12 10:14:02 +02003363 init_translation_status(iommu);
3364
Joerg Roedel091d42e2015-06-12 11:56:10 +02003365 if (translation_pre_enabled(iommu) && !is_kdump_kernel()) {
3366 iommu_disable_translation(iommu);
3367 clear_translation_pre_enabled(iommu);
3368 pr_warn("Translation was enabled for %s but we are not in kdump mode\n",
3369 iommu->name);
3370 }
Joerg Roedel4158c2e2015-06-12 10:14:02 +02003371
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003372 /*
3373 * TBD:
3374 * we could share the same root & context tables
Lucas De Marchi25985ed2011-03-30 22:57:33 -03003375 * among all IOMMU's. Need to Split it later.
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003376 */
3377 ret = iommu_alloc_root_entry(iommu);
Jiang Liuffebeb42014-11-09 22:48:02 +08003378 if (ret)
Jiang Liu989d51f2014-02-19 14:07:21 +08003379 goto free_iommu;
Joerg Roedel5f0a7f72015-06-12 09:18:53 +02003380
Joerg Roedel091d42e2015-06-12 11:56:10 +02003381 if (translation_pre_enabled(iommu)) {
3382 pr_info("Translation already enabled - trying to copy translation structures\n");
3383
3384 ret = copy_translation_tables(iommu);
3385 if (ret) {
3386 /*
3387 * We found the IOMMU with translation
3388 * enabled - but failed to copy over the
3389 * old root-entry table. Try to proceed
3390 * by disabling translation now and
3391 * allocating a clean root-entry table.
3392 * This might cause DMAR faults, but
3393 * probably the dump will still succeed.
3394 */
3395 pr_err("Failed to copy translation tables from previous kernel for %s\n",
3396 iommu->name);
3397 iommu_disable_translation(iommu);
3398 clear_translation_pre_enabled(iommu);
3399 } else {
3400 pr_info("Copied translation tables from previous kernel for %s\n",
3401 iommu->name);
3402 }
3403 }
3404
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07003405 if (!ecap_pass_through(iommu->ecap))
David Woodhouse19943b02009-08-04 16:19:20 +01003406 hw_pass_through = 0;
Jacob Panff3dc652020-01-02 08:18:03 +08003407 intel_svm_check(iommu);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003408 }
3409
Joerg Roedela4c34ff2016-06-17 11:29:48 +02003410 /*
3411 * Now that qi is enabled on all iommus, set the root entry and flush
3412 * caches. This is required on some Intel X58 chipsets, otherwise the
3413 * flush_context function will loop forever and the boot hangs.
3414 */
3415 for_each_active_iommu(iommu, drhd) {
3416 iommu_flush_write_buffer(iommu);
3417 iommu_set_root_entry(iommu);
3418 iommu->flush.flush_context(iommu, 0, 0, 0, DMA_CCMD_GLOBAL_INVL);
3419 iommu->flush.flush_iotlb(iommu, 0, 0, 0, DMA_TLB_GLOBAL_FLUSH);
3420 }
3421
Suresh Siddhad3f13812011-08-23 17:05:25 -07003422#ifdef CONFIG_INTEL_IOMMU_BROKEN_GFX_WA
Lu Baolu5daab582019-05-02 09:34:26 +08003423 dmar_map_gfx = 0;
David Woodhouse19943b02009-08-04 16:19:20 +01003424#endif
David Woodhousee0fc7e02009-09-30 09:12:17 -07003425
Lu Baolu5daab582019-05-02 09:34:26 +08003426 if (!dmar_map_gfx)
3427 iommu_identity_mapping |= IDENTMAP_GFX;
3428
Ashok Raj21e722c2017-01-30 09:39:53 -08003429 check_tylersburg_isoch();
3430
Lu Baolu4de354e2019-05-25 13:41:27 +08003431 ret = si_domain_init(hw_pass_through);
3432 if (ret)
3433 goto free_iommu;
Joerg Roedel86080cc2015-06-12 12:27:16 +02003434
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003435 /*
3436 * for each drhd
3437 * enable fault log
3438 * global invalidate context cache
3439 * global invalidate iotlb
3440 * enable translation
3441 */
Jiang Liu7c919772014-01-06 14:18:18 +08003442 for_each_iommu(iommu, drhd) {
Joseph Cihula51a63e62011-03-21 11:04:24 -07003443 if (drhd->ignored) {
3444 /*
3445 * we always have to disable PMRs or DMA may fail on
3446 * this device
3447 */
3448 if (force_on)
Jiang Liu7c919772014-01-06 14:18:18 +08003449 iommu_disable_protect_mem_regions(iommu);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003450 continue;
Joseph Cihula51a63e62011-03-21 11:04:24 -07003451 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003452
3453 iommu_flush_write_buffer(iommu);
3454
David Woodhousea222a7f2015-10-07 23:35:18 +01003455#ifdef CONFIG_INTEL_IOMMU_SVM
Lu Baolu765b6a92018-12-10 09:58:55 +08003456 if (pasid_supported(iommu) && ecap_prs(iommu->ecap)) {
Lu Baolua7755c32019-04-19 14:43:29 +08003457 /*
3458 * Call dmar_alloc_hwirq() with dmar_global_lock held,
3459 * could cause possible lock race condition.
3460 */
3461 up_write(&dmar_global_lock);
David Woodhousea222a7f2015-10-07 23:35:18 +01003462 ret = intel_svm_enable_prq(iommu);
Lu Baolua7755c32019-04-19 14:43:29 +08003463 down_write(&dmar_global_lock);
David Woodhousea222a7f2015-10-07 23:35:18 +01003464 if (ret)
3465 goto free_iommu;
3466 }
3467#endif
Keshavamurthy, Anil S3460a6d2007-10-21 16:41:54 -07003468 ret = dmar_set_interrupt(iommu);
3469 if (ret)
Jiang Liu989d51f2014-02-19 14:07:21 +08003470 goto free_iommu;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003471 }
3472
3473 return 0;
Jiang Liu989d51f2014-02-19 14:07:21 +08003474
3475free_iommu:
Jiang Liuffebeb42014-11-09 22:48:02 +08003476 for_each_active_iommu(iommu, drhd) {
3477 disable_dmar_iommu(iommu);
Jiang Liua868e6b2014-01-06 14:18:20 +08003478 free_dmar_iommu(iommu);
Jiang Liuffebeb42014-11-09 22:48:02 +08003479 }
Joerg Roedel13cf0172017-08-11 11:40:10 +02003480
Weidong Hand9630fe2008-12-08 11:06:32 +08003481 kfree(g_iommus);
Joerg Roedel13cf0172017-08-11 11:40:10 +02003482
Jiang Liu989d51f2014-02-19 14:07:21 +08003483error:
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003484 return ret;
3485}
3486
David Woodhouse5a5e02a2009-07-04 09:35:44 +01003487/* This takes a number of _MM_ pages, not VTD pages */
Omer Peleg2aac6302016-04-20 11:33:57 +03003488static unsigned long intel_alloc_iova(struct device *dev,
David Woodhouse875764d2009-06-28 21:20:51 +01003489 struct dmar_domain *domain,
3490 unsigned long nrpages, uint64_t dma_mask)
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003491{
Bjorn Helgaase083ea5b2019-02-08 16:06:08 -06003492 unsigned long iova_pfn;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003493
Lu Baolucb8b8922020-01-02 08:18:19 +08003494 /*
3495 * Restrict dma_mask to the width that the iommu can handle.
3496 * First-level translation restricts the input-address to a
3497 * canonical address (i.e., address bits 63:N have the same
3498 * value as address bit [N-1], where N is 48-bits with 4-level
3499 * paging and 57-bits with 5-level paging). Hence, skip bit
3500 * [N-1].
3501 */
3502 if (domain_use_first_level(domain))
3503 dma_mask = min_t(uint64_t, DOMAIN_MAX_ADDR(domain->gaw - 1),
3504 dma_mask);
3505 else
3506 dma_mask = min_t(uint64_t, DOMAIN_MAX_ADDR(domain->gaw),
3507 dma_mask);
3508
Robin Murphy8f6429c2015-07-16 19:40:12 +01003509 /* Ensure we reserve the whole size-aligned region */
3510 nrpages = __roundup_pow_of_two(nrpages);
David Woodhouse875764d2009-06-28 21:20:51 +01003511
3512 if (!dmar_forcedac && dma_mask > DMA_BIT_MASK(32)) {
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003513 /*
3514 * First try to allocate an io virtual address in
Yang Hongyang284901a2009-04-06 19:01:15 -07003515 * DMA_BIT_MASK(32) and if that fails then try allocating
Joe Perches36098012007-12-17 11:40:11 -08003516 * from higher range
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003517 */
Omer Peleg22e2f9f2016-04-20 11:34:11 +03003518 iova_pfn = alloc_iova_fast(&domain->iovad, nrpages,
Tomasz Nowicki538d5b32017-09-20 10:52:02 +02003519 IOVA_PFN(DMA_BIT_MASK(32)), false);
Omer Peleg22e2f9f2016-04-20 11:34:11 +03003520 if (iova_pfn)
3521 return iova_pfn;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003522 }
Tomasz Nowicki538d5b32017-09-20 10:52:02 +02003523 iova_pfn = alloc_iova_fast(&domain->iovad, nrpages,
3524 IOVA_PFN(dma_mask), true);
Omer Peleg22e2f9f2016-04-20 11:34:11 +03003525 if (unlikely(!iova_pfn)) {
Qian Cai944c9172019-11-22 14:16:54 -05003526 dev_err_once(dev, "Allocating %ld-page iova failed\n",
3527 nrpages);
Omer Peleg2aac6302016-04-20 11:33:57 +03003528 return 0;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003529 }
3530
Omer Peleg22e2f9f2016-04-20 11:34:11 +03003531 return iova_pfn;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003532}
3533
Lu Baolu4ec066c2019-05-25 13:41:33 +08003534static struct dmar_domain *get_private_domain_for_dev(struct device *dev)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003535{
Joerg Roedel1c5ebba2016-08-25 13:52:51 +02003536 struct dmar_domain *domain, *tmp;
Joerg Roedelb1ce5b72015-09-23 19:16:01 +02003537 struct dmar_rmrr_unit *rmrr;
Joerg Roedelb1ce5b72015-09-23 19:16:01 +02003538 struct device *i_dev;
3539 int i, ret;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003540
Lu Baolu4ec066c2019-05-25 13:41:33 +08003541 /* Device shouldn't be attached by any domains. */
Joerg Roedel1c5ebba2016-08-25 13:52:51 +02003542 domain = find_domain(dev);
3543 if (domain)
Lu Baolu4ec066c2019-05-25 13:41:33 +08003544 return NULL;
Joerg Roedel1c5ebba2016-08-25 13:52:51 +02003545
3546 domain = find_or_alloc_domain(dev, DEFAULT_DOMAIN_ADDRESS_WIDTH);
3547 if (!domain)
3548 goto out;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003549
Joerg Roedelb1ce5b72015-09-23 19:16:01 +02003550 /* We have a new domain - setup possible RMRRs for the device */
3551 rcu_read_lock();
3552 for_each_rmrr_units(rmrr) {
3553 for_each_active_dev_scope(rmrr->devices, rmrr->devices_cnt,
3554 i, i_dev) {
3555 if (i_dev != dev)
3556 continue;
3557
3558 ret = domain_prepare_identity_map(dev, domain,
3559 rmrr->base_address,
3560 rmrr->end_address);
3561 if (ret)
3562 dev_err(dev, "Mapping reserved region failed\n");
3563 }
3564 }
3565 rcu_read_unlock();
3566
Joerg Roedel1c5ebba2016-08-25 13:52:51 +02003567 tmp = set_domain_for_dev(dev, domain);
3568 if (!tmp || domain != tmp) {
3569 domain_exit(domain);
3570 domain = tmp;
3571 }
3572
3573out:
Joerg Roedel1c5ebba2016-08-25 13:52:51 +02003574 if (!domain)
Bjorn Helgaas932a6522019-02-08 16:06:00 -06003575 dev_err(dev, "Allocating domain failed\n");
Lu Baoluc57b2602019-06-12 08:28:46 +08003576 else
3577 domain->domain.type = IOMMU_DOMAIN_DMA;
Joerg Roedel1c5ebba2016-08-25 13:52:51 +02003578
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003579 return domain;
3580}
3581
David Woodhouseecb509e2014-03-09 16:29:55 -07003582/* Check if the dev needs to go through non-identity map and unmap process.*/
Christoph Hellwig48b2c932019-04-10 18:14:06 +02003583static bool iommu_need_mapping(struct device *dev)
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003584{
Lu Baolu98b2fff2019-05-25 13:41:30 +08003585 int ret;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003586
David Woodhouse3d891942014-03-06 15:59:26 +00003587 if (iommu_dummy(dev))
Christoph Hellwig48b2c932019-04-10 18:14:06 +02003588 return false;
David Woodhouse1e4c64c2009-07-04 10:40:38 +01003589
Joerg Roedela11bfde2020-02-17 17:20:59 +01003590 if (unlikely(attach_deferred(dev)))
3591 do_deferred_attach(dev);
3592
Lu Baolu98b2fff2019-05-25 13:41:30 +08003593 ret = identity_mapping(dev);
3594 if (ret) {
3595 u64 dma_mask = *dev->dma_mask;
3596
3597 if (dev->coherent_dma_mask && dev->coherent_dma_mask < dma_mask)
3598 dma_mask = dev->coherent_dma_mask;
3599
Arvind Sankar9c24eaf2019-10-08 10:33:57 -04003600 if (dma_mask >= dma_direct_get_required_mask(dev))
Christoph Hellwig48b2c932019-04-10 18:14:06 +02003601 return false;
3602
3603 /*
3604 * 32 bit DMA is removed from si_domain and fall back to
3605 * non-identity mapping.
3606 */
3607 dmar_remove_one_dev_info(dev);
Lu Baolu98b2fff2019-05-25 13:41:30 +08003608 ret = iommu_request_dma_domain_for_dev(dev);
3609 if (ret) {
3610 struct iommu_domain *domain;
3611 struct dmar_domain *dmar_domain;
3612
3613 domain = iommu_get_domain_for_dev(dev);
3614 if (domain) {
3615 dmar_domain = to_dmar_domain(domain);
3616 dmar_domain->flags |= DOMAIN_FLAG_LOSE_CHILDREN;
3617 }
Lu Baoluae23bfb62019-08-06 08:14:08 +08003618 dmar_remove_one_dev_info(dev);
Lu Baolu4ec066c2019-05-25 13:41:33 +08003619 get_private_domain_for_dev(dev);
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003620 }
Lu Baolu98b2fff2019-05-25 13:41:30 +08003621
3622 dev_info(dev, "32bit DMA uses non-identity mapping\n");
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003623 }
3624
Christoph Hellwig48b2c932019-04-10 18:14:06 +02003625 return true;
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003626}
3627
Logan Gunthorpe21d5d272019-01-22 14:30:45 -07003628static dma_addr_t __intel_map_single(struct device *dev, phys_addr_t paddr,
3629 size_t size, int dir, u64 dma_mask)
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003630{
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003631 struct dmar_domain *domain;
Fenghua Yu5b6985c2008-10-16 18:02:32 -07003632 phys_addr_t start_paddr;
Omer Peleg2aac6302016-04-20 11:33:57 +03003633 unsigned long iova_pfn;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003634 int prot = 0;
Ingo Molnar6865f0d2008-04-22 11:09:04 +02003635 int ret;
Weidong Han8c11e792008-12-08 15:29:22 +08003636 struct intel_iommu *iommu;
Fenghua Yu33041ec2009-08-04 15:10:59 -07003637 unsigned long paddr_pfn = paddr >> PAGE_SHIFT;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003638
3639 BUG_ON(dir == DMA_NONE);
Fenghua Yu2c2e2c32009-06-19 13:47:29 -07003640
Joerg Roedel96d170f2020-02-17 17:27:44 +01003641 domain = find_domain(dev);
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003642 if (!domain)
Christoph Hellwig524a6692018-11-21 19:34:10 +01003643 return DMA_MAPPING_ERROR;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003644
Weidong Han8c11e792008-12-08 15:29:22 +08003645 iommu = domain_get_iommu(domain);
David Woodhouse88cb6a72009-06-28 15:03:06 +01003646 size = aligned_nrpages(paddr, size);
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003647
Omer Peleg2aac6302016-04-20 11:33:57 +03003648 iova_pfn = intel_alloc_iova(dev, domain, dma_to_mm_pfn(size), dma_mask);
3649 if (!iova_pfn)
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003650 goto error;
3651
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003652 /*
3653 * Check if DMAR supports zero-length reads on write only
3654 * mappings..
3655 */
3656 if (dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL || \
Weidong Han8c11e792008-12-08 15:29:22 +08003657 !cap_zlr(iommu->cap))
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003658 prot |= DMA_PTE_READ;
3659 if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL)
3660 prot |= DMA_PTE_WRITE;
3661 /*
Ingo Molnar6865f0d2008-04-22 11:09:04 +02003662 * paddr - (paddr + size) might be partial page, we should map the whole
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003663 * page. Note: if two part of one page are separately mapped, we
Ingo Molnar6865f0d2008-04-22 11:09:04 +02003664 * might have two guest_addr mapping to the same host paddr, but this
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003665 * is not a big problem
3666 */
Omer Peleg2aac6302016-04-20 11:33:57 +03003667 ret = domain_pfn_mapping(domain, mm_to_dma_pfn(iova_pfn),
Fenghua Yu33041ec2009-08-04 15:10:59 -07003668 mm_to_dma_pfn(paddr_pfn), size, prot);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003669 if (ret)
3670 goto error;
3671
Omer Peleg2aac6302016-04-20 11:33:57 +03003672 start_paddr = (phys_addr_t)iova_pfn << PAGE_SHIFT;
David Woodhouse03d6a242009-06-28 15:33:46 +01003673 start_paddr += paddr & ~PAGE_MASK;
Lu Baolu3b530342019-09-06 14:14:51 +08003674
3675 trace_map_single(dev, start_paddr, paddr, size << VTD_PAGE_SHIFT);
3676
David Woodhouse03d6a242009-06-28 15:33:46 +01003677 return start_paddr;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003678
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003679error:
Omer Peleg2aac6302016-04-20 11:33:57 +03003680 if (iova_pfn)
Omer Peleg22e2f9f2016-04-20 11:34:11 +03003681 free_iova_fast(&domain->iovad, iova_pfn, dma_to_mm_pfn(size));
Bjorn Helgaas932a6522019-02-08 16:06:00 -06003682 dev_err(dev, "Device request: %zx@%llx dir %d --- failed\n",
3683 size, (unsigned long long)paddr, dir);
Christoph Hellwig524a6692018-11-21 19:34:10 +01003684 return DMA_MAPPING_ERROR;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003685}
3686
FUJITA Tomonoriffbbef52009-01-05 23:47:26 +09003687static dma_addr_t intel_map_page(struct device *dev, struct page *page,
3688 unsigned long offset, size_t size,
3689 enum dma_data_direction dir,
Krzysztof Kozlowski00085f12016-08-03 13:46:00 -07003690 unsigned long attrs)
FUJITA Tomonoribb9e6d62008-10-15 16:08:28 +09003691{
Christoph Hellwig9cc0c2a2019-04-10 18:14:07 +02003692 if (iommu_need_mapping(dev))
3693 return __intel_map_single(dev, page_to_phys(page) + offset,
3694 size, dir, *dev->dma_mask);
3695 return dma_direct_map_page(dev, page, offset, size, dir, attrs);
Logan Gunthorpe21d5d272019-01-22 14:30:45 -07003696}
3697
3698static dma_addr_t intel_map_resource(struct device *dev, phys_addr_t phys_addr,
3699 size_t size, enum dma_data_direction dir,
3700 unsigned long attrs)
3701{
Christoph Hellwig9cc0c2a2019-04-10 18:14:07 +02003702 if (iommu_need_mapping(dev))
3703 return __intel_map_single(dev, phys_addr, size, dir,
3704 *dev->dma_mask);
3705 return dma_direct_map_resource(dev, phys_addr, size, dir, attrs);
FUJITA Tomonoribb9e6d62008-10-15 16:08:28 +09003706}
3707
Omer Peleg769530e2016-04-20 11:33:25 +03003708static void intel_unmap(struct device *dev, dma_addr_t dev_addr, size_t size)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003709{
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003710 struct dmar_domain *domain;
David Woodhoused794dc92009-06-28 00:27:49 +01003711 unsigned long start_pfn, last_pfn;
Omer Peleg769530e2016-04-20 11:33:25 +03003712 unsigned long nrpages;
Omer Peleg2aac6302016-04-20 11:33:57 +03003713 unsigned long iova_pfn;
Weidong Han8c11e792008-12-08 15:29:22 +08003714 struct intel_iommu *iommu;
David Woodhouseea8ea462014-03-05 17:09:32 +00003715 struct page *freelist;
Lu Baoluf7b0c4c2019-04-12 12:26:13 +08003716 struct pci_dev *pdev = NULL;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003717
David Woodhouse1525a292014-03-06 16:19:30 +00003718 domain = find_domain(dev);
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003719 BUG_ON(!domain);
3720
Weidong Han8c11e792008-12-08 15:29:22 +08003721 iommu = domain_get_iommu(domain);
3722
Omer Peleg2aac6302016-04-20 11:33:57 +03003723 iova_pfn = IOVA_PFN(dev_addr);
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003724
Omer Peleg769530e2016-04-20 11:33:25 +03003725 nrpages = aligned_nrpages(dev_addr, size);
Omer Peleg2aac6302016-04-20 11:33:57 +03003726 start_pfn = mm_to_dma_pfn(iova_pfn);
Omer Peleg769530e2016-04-20 11:33:25 +03003727 last_pfn = start_pfn + nrpages - 1;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003728
Lu Baoluf7b0c4c2019-04-12 12:26:13 +08003729 if (dev_is_pci(dev))
3730 pdev = to_pci_dev(dev);
3731
David Woodhouseea8ea462014-03-05 17:09:32 +00003732 freelist = domain_unmap(domain, start_pfn, last_pfn);
Dmitry Safonoveffa4672019-07-16 22:38:05 +01003733 if (intel_iommu_strict || (pdev && pdev->untrusted) ||
3734 !has_iova_flush_queue(&domain->iovad)) {
Joerg Roedela1ddcbe2015-07-21 15:20:32 +02003735 iommu_flush_iotlb_psi(iommu, domain, start_pfn,
Omer Peleg769530e2016-04-20 11:33:25 +03003736 nrpages, !freelist, 0);
mark gross5e0d2a62008-03-04 15:22:08 -08003737 /* free iova */
Omer Peleg22e2f9f2016-04-20 11:34:11 +03003738 free_iova_fast(&domain->iovad, iova_pfn, dma_to_mm_pfn(nrpages));
David Woodhouseea8ea462014-03-05 17:09:32 +00003739 dma_free_pagelist(freelist);
mark gross5e0d2a62008-03-04 15:22:08 -08003740 } else {
Joerg Roedel13cf0172017-08-11 11:40:10 +02003741 queue_iova(&domain->iovad, iova_pfn, nrpages,
3742 (unsigned long)freelist);
mark gross5e0d2a62008-03-04 15:22:08 -08003743 /*
3744 * queue up the release of the unmap to save the 1/6th of the
3745 * cpu used up by the iotlb flush operation...
3746 */
mark gross5e0d2a62008-03-04 15:22:08 -08003747 }
Lu Baolu3b530342019-09-06 14:14:51 +08003748
3749 trace_unmap_single(dev, dev_addr, size);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003750}
3751
Jiang Liud41a4ad2014-07-11 14:19:34 +08003752static void intel_unmap_page(struct device *dev, dma_addr_t dev_addr,
3753 size_t size, enum dma_data_direction dir,
Krzysztof Kozlowski00085f12016-08-03 13:46:00 -07003754 unsigned long attrs)
Jiang Liud41a4ad2014-07-11 14:19:34 +08003755{
Christoph Hellwig9cc0c2a2019-04-10 18:14:07 +02003756 if (iommu_need_mapping(dev))
3757 intel_unmap(dev, dev_addr, size);
3758 else
3759 dma_direct_unmap_page(dev, dev_addr, size, dir, attrs);
3760}
3761
3762static void intel_unmap_resource(struct device *dev, dma_addr_t dev_addr,
3763 size_t size, enum dma_data_direction dir, unsigned long attrs)
3764{
3765 if (iommu_need_mapping(dev))
3766 intel_unmap(dev, dev_addr, size);
Jiang Liud41a4ad2014-07-11 14:19:34 +08003767}
3768
David Woodhouse5040a912014-03-09 16:14:00 -07003769static void *intel_alloc_coherent(struct device *dev, size_t size,
Andrzej Pietrasiewiczbaa676f2012-03-27 14:28:18 +02003770 dma_addr_t *dma_handle, gfp_t flags,
Krzysztof Kozlowski00085f12016-08-03 13:46:00 -07003771 unsigned long attrs)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003772{
Christoph Hellwig7ec916f2018-07-05 13:29:55 -06003773 struct page *page = NULL;
3774 int order;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003775
Christoph Hellwig9cc0c2a2019-04-10 18:14:07 +02003776 if (!iommu_need_mapping(dev))
3777 return dma_direct_alloc(dev, size, dma_handle, flags, attrs);
3778
Christoph Hellwig7ec916f2018-07-05 13:29:55 -06003779 size = PAGE_ALIGN(size);
3780 order = get_order(size);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003781
Christoph Hellwig7ec916f2018-07-05 13:29:55 -06003782 if (gfpflags_allow_blocking(flags)) {
3783 unsigned int count = size >> PAGE_SHIFT;
3784
Marek Szyprowskid834c5a2018-08-17 15:49:00 -07003785 page = dma_alloc_from_contiguous(dev, count, order,
3786 flags & __GFP_NOWARN);
Christoph Hellwig7ec916f2018-07-05 13:29:55 -06003787 }
3788
3789 if (!page)
3790 page = alloc_pages(flags, order);
3791 if (!page)
3792 return NULL;
3793 memset(page_address(page), 0, size);
3794
Logan Gunthorpe21d5d272019-01-22 14:30:45 -07003795 *dma_handle = __intel_map_single(dev, page_to_phys(page), size,
3796 DMA_BIDIRECTIONAL,
3797 dev->coherent_dma_mask);
Christoph Hellwig524a6692018-11-21 19:34:10 +01003798 if (*dma_handle != DMA_MAPPING_ERROR)
Christoph Hellwig7ec916f2018-07-05 13:29:55 -06003799 return page_address(page);
3800 if (!dma_release_from_contiguous(dev, page, size >> PAGE_SHIFT))
3801 __free_pages(page, order);
3802
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003803 return NULL;
3804}
3805
David Woodhouse5040a912014-03-09 16:14:00 -07003806static void intel_free_coherent(struct device *dev, size_t size, void *vaddr,
Krzysztof Kozlowski00085f12016-08-03 13:46:00 -07003807 dma_addr_t dma_handle, unsigned long attrs)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003808{
Christoph Hellwig7ec916f2018-07-05 13:29:55 -06003809 int order;
3810 struct page *page = virt_to_page(vaddr);
3811
Christoph Hellwig9cc0c2a2019-04-10 18:14:07 +02003812 if (!iommu_need_mapping(dev))
3813 return dma_direct_free(dev, size, vaddr, dma_handle, attrs);
3814
Christoph Hellwig7ec916f2018-07-05 13:29:55 -06003815 size = PAGE_ALIGN(size);
3816 order = get_order(size);
3817
3818 intel_unmap(dev, dma_handle, size);
3819 if (!dma_release_from_contiguous(dev, page, size >> PAGE_SHIFT))
3820 __free_pages(page, order);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003821}
3822
David Woodhouse5040a912014-03-09 16:14:00 -07003823static void intel_unmap_sg(struct device *dev, struct scatterlist *sglist,
FUJITA Tomonorid7ab5c42009-01-28 21:53:18 +09003824 int nelems, enum dma_data_direction dir,
Krzysztof Kozlowski00085f12016-08-03 13:46:00 -07003825 unsigned long attrs)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003826{
Omer Peleg769530e2016-04-20 11:33:25 +03003827 dma_addr_t startaddr = sg_dma_address(sglist) & PAGE_MASK;
3828 unsigned long nrpages = 0;
3829 struct scatterlist *sg;
3830 int i;
3831
Christoph Hellwig9cc0c2a2019-04-10 18:14:07 +02003832 if (!iommu_need_mapping(dev))
3833 return dma_direct_unmap_sg(dev, sglist, nelems, dir, attrs);
3834
Omer Peleg769530e2016-04-20 11:33:25 +03003835 for_each_sg(sglist, sg, nelems, i) {
3836 nrpages += aligned_nrpages(sg_dma_address(sg), sg_dma_len(sg));
3837 }
3838
3839 intel_unmap(dev, startaddr, nrpages << VTD_PAGE_SHIFT);
Lu Baolu3b530342019-09-06 14:14:51 +08003840
3841 trace_unmap_sg(dev, startaddr, nrpages << VTD_PAGE_SHIFT);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003842}
3843
David Woodhouse5040a912014-03-09 16:14:00 -07003844static int intel_map_sg(struct device *dev, struct scatterlist *sglist, int nelems,
Krzysztof Kozlowski00085f12016-08-03 13:46:00 -07003845 enum dma_data_direction dir, unsigned long attrs)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003846{
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003847 int i;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003848 struct dmar_domain *domain;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003849 size_t size = 0;
3850 int prot = 0;
Omer Peleg2aac6302016-04-20 11:33:57 +03003851 unsigned long iova_pfn;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003852 int ret;
FUJITA Tomonoric03ab372007-10-21 16:42:00 -07003853 struct scatterlist *sg;
David Woodhouseb536d242009-06-28 14:49:31 +01003854 unsigned long start_vpfn;
Weidong Han8c11e792008-12-08 15:29:22 +08003855 struct intel_iommu *iommu;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003856
3857 BUG_ON(dir == DMA_NONE);
Christoph Hellwig48b2c932019-04-10 18:14:06 +02003858 if (!iommu_need_mapping(dev))
Christoph Hellwig9cc0c2a2019-04-10 18:14:07 +02003859 return dma_direct_map_sg(dev, sglist, nelems, dir, attrs);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003860
Joerg Roedel96d170f2020-02-17 17:27:44 +01003861 domain = find_domain(dev);
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003862 if (!domain)
3863 return 0;
3864
Weidong Han8c11e792008-12-08 15:29:22 +08003865 iommu = domain_get_iommu(domain);
3866
David Woodhouseb536d242009-06-28 14:49:31 +01003867 for_each_sg(sglist, sg, nelems, i)
David Woodhouse88cb6a72009-06-28 15:03:06 +01003868 size += aligned_nrpages(sg->offset, sg->length);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003869
Omer Peleg2aac6302016-04-20 11:33:57 +03003870 iova_pfn = intel_alloc_iova(dev, domain, dma_to_mm_pfn(size),
David Woodhouse5040a912014-03-09 16:14:00 -07003871 *dev->dma_mask);
Omer Peleg2aac6302016-04-20 11:33:57 +03003872 if (!iova_pfn) {
FUJITA Tomonoric03ab372007-10-21 16:42:00 -07003873 sglist->dma_length = 0;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003874 return 0;
3875 }
3876
3877 /*
3878 * Check if DMAR supports zero-length reads on write only
3879 * mappings..
3880 */
3881 if (dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL || \
Weidong Han8c11e792008-12-08 15:29:22 +08003882 !cap_zlr(iommu->cap))
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003883 prot |= DMA_PTE_READ;
3884 if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL)
3885 prot |= DMA_PTE_WRITE;
3886
Omer Peleg2aac6302016-04-20 11:33:57 +03003887 start_vpfn = mm_to_dma_pfn(iova_pfn);
David Woodhousee1605492009-06-29 11:17:38 +01003888
Fenghua Yuf5329592009-08-04 15:09:37 -07003889 ret = domain_sg_mapping(domain, start_vpfn, sglist, size, prot);
David Woodhousee1605492009-06-29 11:17:38 +01003890 if (unlikely(ret)) {
David Woodhousee1605492009-06-29 11:17:38 +01003891 dma_pte_free_pagetable(domain, start_vpfn,
David Dillowbc24c572017-06-28 19:42:23 -07003892 start_vpfn + size - 1,
3893 agaw_to_level(domain->agaw) + 1);
Omer Peleg22e2f9f2016-04-20 11:34:11 +03003894 free_iova_fast(&domain->iovad, iova_pfn, dma_to_mm_pfn(size));
David Woodhousee1605492009-06-29 11:17:38 +01003895 return 0;
Keshavamurthy, Anil Sf76aec72007-10-21 16:41:58 -07003896 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003897
Lu Baolu984d03a2020-01-02 08:18:11 +08003898 for_each_sg(sglist, sg, nelems, i)
3899 trace_map_sg(dev, i + 1, nelems, sg);
Lu Baolu3b530342019-09-06 14:14:51 +08003900
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003901 return nelems;
3902}
3903
Arvind Sankar9c24eaf2019-10-08 10:33:57 -04003904static u64 intel_get_required_mask(struct device *dev)
3905{
3906 if (!iommu_need_mapping(dev))
3907 return dma_direct_get_required_mask(dev);
3908 return DMA_BIT_MASK(32);
3909}
3910
Christoph Hellwig02b4da52018-09-17 19:10:31 +02003911static const struct dma_map_ops intel_dma_ops = {
Andrzej Pietrasiewiczbaa676f2012-03-27 14:28:18 +02003912 .alloc = intel_alloc_coherent,
3913 .free = intel_free_coherent,
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003914 .map_sg = intel_map_sg,
3915 .unmap_sg = intel_unmap_sg,
FUJITA Tomonoriffbbef52009-01-05 23:47:26 +09003916 .map_page = intel_map_page,
3917 .unmap_page = intel_unmap_page,
Logan Gunthorpe21d5d272019-01-22 14:30:45 -07003918 .map_resource = intel_map_resource,
Christoph Hellwig9cc0c2a2019-04-10 18:14:07 +02003919 .unmap_resource = intel_unmap_resource,
Christoph Hellwigfec777c2018-03-19 11:38:15 +01003920 .dma_supported = dma_direct_supported,
Christoph Hellwigf9f32322019-08-06 15:01:50 +03003921 .mmap = dma_common_mmap,
3922 .get_sgtable = dma_common_get_sgtable,
Arvind Sankar9c24eaf2019-10-08 10:33:57 -04003923 .get_required_mask = intel_get_required_mask,
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07003924};
3925
Lu Baolucfb94a32019-09-06 14:14:52 +08003926static void
3927bounce_sync_single(struct device *dev, dma_addr_t addr, size_t size,
3928 enum dma_data_direction dir, enum dma_sync_target target)
3929{
3930 struct dmar_domain *domain;
3931 phys_addr_t tlb_addr;
3932
3933 domain = find_domain(dev);
3934 if (WARN_ON(!domain))
3935 return;
3936
3937 tlb_addr = intel_iommu_iova_to_phys(&domain->domain, addr);
3938 if (is_swiotlb_buffer(tlb_addr))
3939 swiotlb_tbl_sync_single(dev, tlb_addr, size, dir, target);
3940}
3941
3942static dma_addr_t
3943bounce_map_single(struct device *dev, phys_addr_t paddr, size_t size,
3944 enum dma_data_direction dir, unsigned long attrs,
3945 u64 dma_mask)
3946{
3947 size_t aligned_size = ALIGN(size, VTD_PAGE_SIZE);
3948 struct dmar_domain *domain;
3949 struct intel_iommu *iommu;
3950 unsigned long iova_pfn;
3951 unsigned long nrpages;
3952 phys_addr_t tlb_addr;
3953 int prot = 0;
3954 int ret;
3955
Joerg Roedela11bfde2020-02-17 17:20:59 +01003956 if (unlikely(attach_deferred(dev)))
3957 do_deferred_attach(dev);
3958
Joerg Roedel96d170f2020-02-17 17:27:44 +01003959 domain = find_domain(dev);
Joerg Roedela11bfde2020-02-17 17:20:59 +01003960
Lu Baolucfb94a32019-09-06 14:14:52 +08003961 if (WARN_ON(dir == DMA_NONE || !domain))
3962 return DMA_MAPPING_ERROR;
3963
3964 iommu = domain_get_iommu(domain);
3965 if (WARN_ON(!iommu))
3966 return DMA_MAPPING_ERROR;
3967
3968 nrpages = aligned_nrpages(0, size);
3969 iova_pfn = intel_alloc_iova(dev, domain,
3970 dma_to_mm_pfn(nrpages), dma_mask);
3971 if (!iova_pfn)
3972 return DMA_MAPPING_ERROR;
3973
3974 /*
3975 * Check if DMAR supports zero-length reads on write only
3976 * mappings..
3977 */
3978 if (dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL ||
3979 !cap_zlr(iommu->cap))
3980 prot |= DMA_PTE_READ;
3981 if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL)
3982 prot |= DMA_PTE_WRITE;
3983
3984 /*
3985 * If both the physical buffer start address and size are
3986 * page aligned, we don't need to use a bounce page.
3987 */
3988 if (!IS_ALIGNED(paddr | size, VTD_PAGE_SIZE)) {
3989 tlb_addr = swiotlb_tbl_map_single(dev,
3990 __phys_to_dma(dev, io_tlb_start),
3991 paddr, size, aligned_size, dir, attrs);
3992 if (tlb_addr == DMA_MAPPING_ERROR) {
3993 goto swiotlb_error;
3994 } else {
3995 /* Cleanup the padding area. */
3996 void *padding_start = phys_to_virt(tlb_addr);
3997 size_t padding_size = aligned_size;
3998
3999 if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC) &&
4000 (dir == DMA_TO_DEVICE ||
4001 dir == DMA_BIDIRECTIONAL)) {
4002 padding_start += size;
4003 padding_size -= size;
4004 }
4005
4006 memset(padding_start, 0, padding_size);
4007 }
4008 } else {
4009 tlb_addr = paddr;
4010 }
4011
4012 ret = domain_pfn_mapping(domain, mm_to_dma_pfn(iova_pfn),
4013 tlb_addr >> VTD_PAGE_SHIFT, nrpages, prot);
4014 if (ret)
4015 goto mapping_error;
4016
4017 trace_bounce_map_single(dev, iova_pfn << PAGE_SHIFT, paddr, size);
4018
4019 return (phys_addr_t)iova_pfn << PAGE_SHIFT;
4020
4021mapping_error:
4022 if (is_swiotlb_buffer(tlb_addr))
4023 swiotlb_tbl_unmap_single(dev, tlb_addr, size,
4024 aligned_size, dir, attrs);
4025swiotlb_error:
4026 free_iova_fast(&domain->iovad, iova_pfn, dma_to_mm_pfn(nrpages));
4027 dev_err(dev, "Device bounce map: %zx@%llx dir %d --- failed\n",
4028 size, (unsigned long long)paddr, dir);
4029
4030 return DMA_MAPPING_ERROR;
4031}
4032
4033static void
4034bounce_unmap_single(struct device *dev, dma_addr_t dev_addr, size_t size,
4035 enum dma_data_direction dir, unsigned long attrs)
4036{
4037 size_t aligned_size = ALIGN(size, VTD_PAGE_SIZE);
4038 struct dmar_domain *domain;
4039 phys_addr_t tlb_addr;
4040
4041 domain = find_domain(dev);
4042 if (WARN_ON(!domain))
4043 return;
4044
4045 tlb_addr = intel_iommu_iova_to_phys(&domain->domain, dev_addr);
4046 if (WARN_ON(!tlb_addr))
4047 return;
4048
4049 intel_unmap(dev, dev_addr, size);
4050 if (is_swiotlb_buffer(tlb_addr))
4051 swiotlb_tbl_unmap_single(dev, tlb_addr, size,
4052 aligned_size, dir, attrs);
4053
4054 trace_bounce_unmap_single(dev, dev_addr, size);
4055}
4056
4057static dma_addr_t
4058bounce_map_page(struct device *dev, struct page *page, unsigned long offset,
4059 size_t size, enum dma_data_direction dir, unsigned long attrs)
4060{
4061 return bounce_map_single(dev, page_to_phys(page) + offset,
4062 size, dir, attrs, *dev->dma_mask);
4063}
4064
4065static dma_addr_t
4066bounce_map_resource(struct device *dev, phys_addr_t phys_addr, size_t size,
4067 enum dma_data_direction dir, unsigned long attrs)
4068{
4069 return bounce_map_single(dev, phys_addr, size,
4070 dir, attrs, *dev->dma_mask);
4071}
4072
4073static void
4074bounce_unmap_page(struct device *dev, dma_addr_t dev_addr, size_t size,
4075 enum dma_data_direction dir, unsigned long attrs)
4076{
4077 bounce_unmap_single(dev, dev_addr, size, dir, attrs);
4078}
4079
4080static void
4081bounce_unmap_resource(struct device *dev, dma_addr_t dev_addr, size_t size,
4082 enum dma_data_direction dir, unsigned long attrs)
4083{
4084 bounce_unmap_single(dev, dev_addr, size, dir, attrs);
4085}
4086
4087static void
4088bounce_unmap_sg(struct device *dev, struct scatterlist *sglist, int nelems,
4089 enum dma_data_direction dir, unsigned long attrs)
4090{
4091 struct scatterlist *sg;
4092 int i;
4093
4094 for_each_sg(sglist, sg, nelems, i)
4095 bounce_unmap_page(dev, sg->dma_address,
4096 sg_dma_len(sg), dir, attrs);
4097}
4098
4099static int
4100bounce_map_sg(struct device *dev, struct scatterlist *sglist, int nelems,
4101 enum dma_data_direction dir, unsigned long attrs)
4102{
4103 int i;
4104 struct scatterlist *sg;
4105
4106 for_each_sg(sglist, sg, nelems, i) {
4107 sg->dma_address = bounce_map_page(dev, sg_page(sg),
4108 sg->offset, sg->length,
4109 dir, attrs);
4110 if (sg->dma_address == DMA_MAPPING_ERROR)
4111 goto out_unmap;
4112 sg_dma_len(sg) = sg->length;
4113 }
4114
Lu Baolu984d03a2020-01-02 08:18:11 +08004115 for_each_sg(sglist, sg, nelems, i)
4116 trace_bounce_map_sg(dev, i + 1, nelems, sg);
4117
Lu Baolucfb94a32019-09-06 14:14:52 +08004118 return nelems;
4119
4120out_unmap:
4121 bounce_unmap_sg(dev, sglist, i, dir, attrs | DMA_ATTR_SKIP_CPU_SYNC);
4122 return 0;
4123}
4124
4125static void
4126bounce_sync_single_for_cpu(struct device *dev, dma_addr_t addr,
4127 size_t size, enum dma_data_direction dir)
4128{
4129 bounce_sync_single(dev, addr, size, dir, SYNC_FOR_CPU);
4130}
4131
4132static void
4133bounce_sync_single_for_device(struct device *dev, dma_addr_t addr,
4134 size_t size, enum dma_data_direction dir)
4135{
4136 bounce_sync_single(dev, addr, size, dir, SYNC_FOR_DEVICE);
4137}
4138
4139static void
4140bounce_sync_sg_for_cpu(struct device *dev, struct scatterlist *sglist,
4141 int nelems, enum dma_data_direction dir)
4142{
4143 struct scatterlist *sg;
4144 int i;
4145
4146 for_each_sg(sglist, sg, nelems, i)
4147 bounce_sync_single(dev, sg_dma_address(sg),
4148 sg_dma_len(sg), dir, SYNC_FOR_CPU);
4149}
4150
4151static void
4152bounce_sync_sg_for_device(struct device *dev, struct scatterlist *sglist,
4153 int nelems, enum dma_data_direction dir)
4154{
4155 struct scatterlist *sg;
4156 int i;
4157
4158 for_each_sg(sglist, sg, nelems, i)
4159 bounce_sync_single(dev, sg_dma_address(sg),
4160 sg_dma_len(sg), dir, SYNC_FOR_DEVICE);
4161}
4162
4163static const struct dma_map_ops bounce_dma_ops = {
4164 .alloc = intel_alloc_coherent,
4165 .free = intel_free_coherent,
4166 .map_sg = bounce_map_sg,
4167 .unmap_sg = bounce_unmap_sg,
4168 .map_page = bounce_map_page,
4169 .unmap_page = bounce_unmap_page,
4170 .sync_single_for_cpu = bounce_sync_single_for_cpu,
4171 .sync_single_for_device = bounce_sync_single_for_device,
4172 .sync_sg_for_cpu = bounce_sync_sg_for_cpu,
4173 .sync_sg_for_device = bounce_sync_sg_for_device,
4174 .map_resource = bounce_map_resource,
4175 .unmap_resource = bounce_unmap_resource,
4176 .dma_supported = dma_direct_supported,
4177};
4178
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004179static inline int iommu_domain_cache_init(void)
4180{
4181 int ret = 0;
4182
4183 iommu_domain_cache = kmem_cache_create("iommu_domain",
4184 sizeof(struct dmar_domain),
4185 0,
4186 SLAB_HWCACHE_ALIGN,
4187
4188 NULL);
4189 if (!iommu_domain_cache) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02004190 pr_err("Couldn't create iommu_domain cache\n");
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004191 ret = -ENOMEM;
4192 }
4193
4194 return ret;
4195}
4196
4197static inline int iommu_devinfo_cache_init(void)
4198{
4199 int ret = 0;
4200
4201 iommu_devinfo_cache = kmem_cache_create("iommu_devinfo",
4202 sizeof(struct device_domain_info),
4203 0,
4204 SLAB_HWCACHE_ALIGN,
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004205 NULL);
4206 if (!iommu_devinfo_cache) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02004207 pr_err("Couldn't create devinfo cache\n");
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004208 ret = -ENOMEM;
4209 }
4210
4211 return ret;
4212}
4213
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004214static int __init iommu_init_mempool(void)
4215{
4216 int ret;
Sakari Ailusae1ff3d2015-07-13 14:31:28 +03004217 ret = iova_cache_get();
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004218 if (ret)
4219 return ret;
4220
4221 ret = iommu_domain_cache_init();
4222 if (ret)
4223 goto domain_error;
4224
4225 ret = iommu_devinfo_cache_init();
4226 if (!ret)
4227 return ret;
4228
4229 kmem_cache_destroy(iommu_domain_cache);
4230domain_error:
Sakari Ailusae1ff3d2015-07-13 14:31:28 +03004231 iova_cache_put();
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004232
4233 return -ENOMEM;
4234}
4235
4236static void __init iommu_exit_mempool(void)
4237{
4238 kmem_cache_destroy(iommu_devinfo_cache);
4239 kmem_cache_destroy(iommu_domain_cache);
Sakari Ailusae1ff3d2015-07-13 14:31:28 +03004240 iova_cache_put();
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004241}
4242
Dan Williams556ab452010-07-23 15:47:56 -07004243static void quirk_ioat_snb_local_iommu(struct pci_dev *pdev)
4244{
4245 struct dmar_drhd_unit *drhd;
4246 u32 vtbar;
4247 int rc;
4248
4249 /* We know that this device on this chipset has its own IOMMU.
4250 * If we find it under a different IOMMU, then the BIOS is lying
4251 * to us. Hope that the IOMMU for this device is actually
4252 * disabled, and it needs no translation...
4253 */
4254 rc = pci_bus_read_config_dword(pdev->bus, PCI_DEVFN(0, 0), 0xb0, &vtbar);
4255 if (rc) {
4256 /* "can't" happen */
4257 dev_info(&pdev->dev, "failed to run vt-d quirk\n");
4258 return;
4259 }
4260 vtbar &= 0xffff0000;
4261
4262 /* we know that the this iommu should be at offset 0xa000 from vtbar */
4263 drhd = dmar_find_matched_drhd_unit(pdev);
4264 if (WARN_TAINT_ONCE(!drhd || drhd->reg_base_addr - vtbar != 0xa000,
4265 TAINT_FIRMWARE_WORKAROUND,
4266 "BIOS assigned incorrect VT-d unit for Intel(R) QuickData Technology device\n"))
4267 pdev->dev.archdata.iommu = DUMMY_DEVICE_DOMAIN_INFO;
4268}
4269DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_SNB, quirk_ioat_snb_local_iommu);
4270
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004271static void __init init_no_remapping_devices(void)
4272{
4273 struct dmar_drhd_unit *drhd;
David Woodhouse832bd852014-03-07 15:08:36 +00004274 struct device *dev;
Jiang Liub683b232014-02-19 14:07:32 +08004275 int i;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004276
4277 for_each_drhd_unit(drhd) {
4278 if (!drhd->include_all) {
Jiang Liub683b232014-02-19 14:07:32 +08004279 for_each_active_dev_scope(drhd->devices,
4280 drhd->devices_cnt, i, dev)
4281 break;
David Woodhouse832bd852014-03-07 15:08:36 +00004282 /* ignore DMAR unit if no devices exist */
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004283 if (i == drhd->devices_cnt)
4284 drhd->ignored = 1;
4285 }
4286 }
4287
Jiang Liu7c919772014-01-06 14:18:18 +08004288 for_each_active_drhd_unit(drhd) {
Jiang Liu7c919772014-01-06 14:18:18 +08004289 if (drhd->include_all)
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004290 continue;
4291
Jiang Liub683b232014-02-19 14:07:32 +08004292 for_each_active_dev_scope(drhd->devices,
4293 drhd->devices_cnt, i, dev)
David Woodhouse832bd852014-03-07 15:08:36 +00004294 if (!dev_is_pci(dev) || !IS_GFX_DEVICE(to_pci_dev(dev)))
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004295 break;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004296 if (i < drhd->devices_cnt)
4297 continue;
4298
David Woodhousec0771df2011-10-14 20:59:46 +01004299 /* This IOMMU has *only* gfx devices. Either bypass it or
4300 set the gfx_mapped flag, as appropriate */
Lu Baolucf1ec452019-05-02 09:34:25 +08004301 if (!dmar_map_gfx) {
David Woodhousec0771df2011-10-14 20:59:46 +01004302 drhd->ignored = 1;
Jiang Liub683b232014-02-19 14:07:32 +08004303 for_each_active_dev_scope(drhd->devices,
4304 drhd->devices_cnt, i, dev)
David Woodhouse832bd852014-03-07 15:08:36 +00004305 dev->archdata.iommu = DUMMY_DEVICE_DOMAIN_INFO;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07004306 }
4307 }
4308}
4309
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004310#ifdef CONFIG_SUSPEND
4311static int init_iommu_hw(void)
4312{
4313 struct dmar_drhd_unit *drhd;
4314 struct intel_iommu *iommu = NULL;
4315
4316 for_each_active_iommu(iommu, drhd)
4317 if (iommu->qi)
4318 dmar_reenable_qi(iommu);
4319
Joseph Cihulab7792602011-05-03 00:08:37 -07004320 for_each_iommu(iommu, drhd) {
4321 if (drhd->ignored) {
4322 /*
4323 * we always have to disable PMRs or DMA may fail on
4324 * this device
4325 */
4326 if (force_on)
4327 iommu_disable_protect_mem_regions(iommu);
4328 continue;
4329 }
Lu Baolu095303e2019-04-29 09:16:02 +08004330
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004331 iommu_flush_write_buffer(iommu);
4332
4333 iommu_set_root_entry(iommu);
4334
4335 iommu->flush.flush_context(iommu, 0, 0, 0,
David Woodhouse1f0ef2a2009-05-10 19:58:49 +01004336 DMA_CCMD_GLOBAL_INVL);
Jiang Liu2a41cce2014-07-11 14:19:33 +08004337 iommu->flush.flush_iotlb(iommu, 0, 0, 0, DMA_TLB_GLOBAL_FLUSH);
4338 iommu_enable_translation(iommu);
David Woodhouseb94996c2009-09-19 15:28:12 -07004339 iommu_disable_protect_mem_regions(iommu);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004340 }
4341
4342 return 0;
4343}
4344
4345static void iommu_flush_all(void)
4346{
4347 struct dmar_drhd_unit *drhd;
4348 struct intel_iommu *iommu;
4349
4350 for_each_active_iommu(iommu, drhd) {
4351 iommu->flush.flush_context(iommu, 0, 0, 0,
David Woodhouse1f0ef2a2009-05-10 19:58:49 +01004352 DMA_CCMD_GLOBAL_INVL);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004353 iommu->flush.flush_iotlb(iommu, 0, 0, 0,
David Woodhouse1f0ef2a2009-05-10 19:58:49 +01004354 DMA_TLB_GLOBAL_FLUSH);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004355 }
4356}
4357
Rafael J. Wysocki134fac32011-03-23 22:16:14 +01004358static int iommu_suspend(void)
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004359{
4360 struct dmar_drhd_unit *drhd;
4361 struct intel_iommu *iommu = NULL;
4362 unsigned long flag;
4363
4364 for_each_active_iommu(iommu, drhd) {
Kees Cook6396bb22018-06-12 14:03:40 -07004365 iommu->iommu_state = kcalloc(MAX_SR_DMAR_REGS, sizeof(u32),
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004366 GFP_ATOMIC);
4367 if (!iommu->iommu_state)
4368 goto nomem;
4369 }
4370
4371 iommu_flush_all();
4372
4373 for_each_active_iommu(iommu, drhd) {
4374 iommu_disable_translation(iommu);
4375
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02004376 raw_spin_lock_irqsave(&iommu->register_lock, flag);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004377
4378 iommu->iommu_state[SR_DMAR_FECTL_REG] =
4379 readl(iommu->reg + DMAR_FECTL_REG);
4380 iommu->iommu_state[SR_DMAR_FEDATA_REG] =
4381 readl(iommu->reg + DMAR_FEDATA_REG);
4382 iommu->iommu_state[SR_DMAR_FEADDR_REG] =
4383 readl(iommu->reg + DMAR_FEADDR_REG);
4384 iommu->iommu_state[SR_DMAR_FEUADDR_REG] =
4385 readl(iommu->reg + DMAR_FEUADDR_REG);
4386
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02004387 raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004388 }
4389 return 0;
4390
4391nomem:
4392 for_each_active_iommu(iommu, drhd)
4393 kfree(iommu->iommu_state);
4394
4395 return -ENOMEM;
4396}
4397
Rafael J. Wysocki134fac32011-03-23 22:16:14 +01004398static void iommu_resume(void)
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004399{
4400 struct dmar_drhd_unit *drhd;
4401 struct intel_iommu *iommu = NULL;
4402 unsigned long flag;
4403
4404 if (init_iommu_hw()) {
Joseph Cihulab7792602011-05-03 00:08:37 -07004405 if (force_on)
4406 panic("tboot: IOMMU setup failed, DMAR can not resume!\n");
4407 else
4408 WARN(1, "IOMMU setup failed, DMAR can not resume!\n");
Rafael J. Wysocki134fac32011-03-23 22:16:14 +01004409 return;
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004410 }
4411
4412 for_each_active_iommu(iommu, drhd) {
4413
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02004414 raw_spin_lock_irqsave(&iommu->register_lock, flag);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004415
4416 writel(iommu->iommu_state[SR_DMAR_FECTL_REG],
4417 iommu->reg + DMAR_FECTL_REG);
4418 writel(iommu->iommu_state[SR_DMAR_FEDATA_REG],
4419 iommu->reg + DMAR_FEDATA_REG);
4420 writel(iommu->iommu_state[SR_DMAR_FEADDR_REG],
4421 iommu->reg + DMAR_FEADDR_REG);
4422 writel(iommu->iommu_state[SR_DMAR_FEUADDR_REG],
4423 iommu->reg + DMAR_FEUADDR_REG);
4424
Thomas Gleixner1f5b3c32011-07-19 16:19:51 +02004425 raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004426 }
4427
4428 for_each_active_iommu(iommu, drhd)
4429 kfree(iommu->iommu_state);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004430}
4431
Rafael J. Wysocki134fac32011-03-23 22:16:14 +01004432static struct syscore_ops iommu_syscore_ops = {
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004433 .resume = iommu_resume,
4434 .suspend = iommu_suspend,
4435};
4436
Rafael J. Wysocki134fac32011-03-23 22:16:14 +01004437static void __init init_iommu_pm_ops(void)
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004438{
Rafael J. Wysocki134fac32011-03-23 22:16:14 +01004439 register_syscore_ops(&iommu_syscore_ops);
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004440}
4441
4442#else
Rafael J. Wysocki99592ba2011-06-07 21:32:31 +02004443static inline void init_iommu_pm_ops(void) {}
Fenghua Yuf59c7b62009-03-27 14:22:42 -07004444#endif /* CONFIG_PM */
4445
Barret Rhodence4cc52b2020-01-15 11:03:57 +08004446static int rmrr_sanity_check(struct acpi_dmar_reserved_memory *rmrr)
4447{
4448 if (!IS_ALIGNED(rmrr->base_address, PAGE_SIZE) ||
4449 !IS_ALIGNED(rmrr->end_address + 1, PAGE_SIZE) ||
4450 rmrr->end_address <= rmrr->base_address ||
4451 arch_rmrr_sanity_check(rmrr))
4452 return -EINVAL;
4453
4454 return 0;
4455}
4456
Jiang Liuc2a0b532014-11-09 22:47:56 +08004457int __init dmar_parse_one_rmrr(struct acpi_dmar_header *header, void *arg)
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004458{
4459 struct acpi_dmar_reserved_memory *rmrr;
4460 struct dmar_rmrr_unit *rmrru;
Yian Chenf036c7f2019-10-17 04:39:19 -07004461
4462 rmrr = (struct acpi_dmar_reserved_memory *)header;
Barret Rhodence4cc52b2020-01-15 11:03:57 +08004463 if (rmrr_sanity_check(rmrr))
Barret Rhodenf5a68bb2020-01-15 11:03:56 +08004464 WARN_TAINT(1, TAINT_FIRMWARE_WORKAROUND,
4465 "Your BIOS is broken; bad RMRR [%#018Lx-%#018Lx]\n"
4466 "BIOS vendor: %s; Ver: %s; Product Version: %s\n",
4467 rmrr->base_address, rmrr->end_address,
4468 dmi_get_system_info(DMI_BIOS_VENDOR),
4469 dmi_get_system_info(DMI_BIOS_VERSION),
4470 dmi_get_system_info(DMI_PRODUCT_VERSION));
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004471
4472 rmrru = kzalloc(sizeof(*rmrru), GFP_KERNEL);
4473 if (!rmrru)
Eric Auger0659b8d2017-01-19 20:57:53 +00004474 goto out;
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004475
4476 rmrru->hdr = header;
Yian Chenf036c7f2019-10-17 04:39:19 -07004477
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004478 rmrru->base_address = rmrr->base_address;
4479 rmrru->end_address = rmrr->end_address;
Eric Auger0659b8d2017-01-19 20:57:53 +00004480
Jiang Liu2e455282014-02-19 14:07:36 +08004481 rmrru->devices = dmar_alloc_dev_scope((void *)(rmrr + 1),
4482 ((void *)rmrr) + rmrr->header.length,
4483 &rmrru->devices_cnt);
Eric Auger0659b8d2017-01-19 20:57:53 +00004484 if (rmrru->devices_cnt && rmrru->devices == NULL)
Eric Auger5f64ce52019-06-03 08:53:31 +02004485 goto free_rmrru;
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004486
Jiang Liu2e455282014-02-19 14:07:36 +08004487 list_add(&rmrru->list, &dmar_rmrr_units);
4488
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004489 return 0;
Eric Auger0659b8d2017-01-19 20:57:53 +00004490free_rmrru:
4491 kfree(rmrru);
4492out:
4493 return -ENOMEM;
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004494}
4495
Jiang Liu6b197242014-11-09 22:47:58 +08004496static struct dmar_atsr_unit *dmar_find_atsr(struct acpi_dmar_atsr *atsr)
4497{
4498 struct dmar_atsr_unit *atsru;
4499 struct acpi_dmar_atsr *tmp;
4500
4501 list_for_each_entry_rcu(atsru, &dmar_atsr_units, list) {
4502 tmp = (struct acpi_dmar_atsr *)atsru->hdr;
4503 if (atsr->segment != tmp->segment)
4504 continue;
4505 if (atsr->header.length != tmp->header.length)
4506 continue;
4507 if (memcmp(atsr, tmp, atsr->header.length) == 0)
4508 return atsru;
4509 }
4510
4511 return NULL;
4512}
4513
4514int dmar_parse_one_atsr(struct acpi_dmar_header *hdr, void *arg)
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004515{
4516 struct acpi_dmar_atsr *atsr;
4517 struct dmar_atsr_unit *atsru;
4518
Thomas Gleixnerb608fe32017-05-16 20:42:41 +02004519 if (system_state >= SYSTEM_RUNNING && !intel_iommu_enabled)
Jiang Liu6b197242014-11-09 22:47:58 +08004520 return 0;
4521
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004522 atsr = container_of(hdr, struct acpi_dmar_atsr, header);
Jiang Liu6b197242014-11-09 22:47:58 +08004523 atsru = dmar_find_atsr(atsr);
4524 if (atsru)
4525 return 0;
4526
4527 atsru = kzalloc(sizeof(*atsru) + hdr->length, GFP_KERNEL);
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004528 if (!atsru)
4529 return -ENOMEM;
4530
Jiang Liu6b197242014-11-09 22:47:58 +08004531 /*
4532 * If memory is allocated from slab by ACPI _DSM method, we need to
4533 * copy the memory content because the memory buffer will be freed
4534 * on return.
4535 */
4536 atsru->hdr = (void *)(atsru + 1);
4537 memcpy(atsru->hdr, hdr, hdr->length);
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004538 atsru->include_all = atsr->flags & 0x1;
Jiang Liu2e455282014-02-19 14:07:36 +08004539 if (!atsru->include_all) {
4540 atsru->devices = dmar_alloc_dev_scope((void *)(atsr + 1),
4541 (void *)atsr + atsr->header.length,
4542 &atsru->devices_cnt);
4543 if (atsru->devices_cnt && atsru->devices == NULL) {
4544 kfree(atsru);
4545 return -ENOMEM;
4546 }
4547 }
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004548
Jiang Liu0e242612014-02-19 14:07:34 +08004549 list_add_rcu(&atsru->list, &dmar_atsr_units);
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004550
4551 return 0;
4552}
4553
Jiang Liu9bdc5312014-01-06 14:18:27 +08004554static void intel_iommu_free_atsr(struct dmar_atsr_unit *atsru)
4555{
4556 dmar_free_dev_scope(&atsru->devices, &atsru->devices_cnt);
4557 kfree(atsru);
4558}
4559
Jiang Liu6b197242014-11-09 22:47:58 +08004560int dmar_release_one_atsr(struct acpi_dmar_header *hdr, void *arg)
4561{
4562 struct acpi_dmar_atsr *atsr;
4563 struct dmar_atsr_unit *atsru;
4564
4565 atsr = container_of(hdr, struct acpi_dmar_atsr, header);
4566 atsru = dmar_find_atsr(atsr);
4567 if (atsru) {
4568 list_del_rcu(&atsru->list);
4569 synchronize_rcu();
4570 intel_iommu_free_atsr(atsru);
4571 }
4572
4573 return 0;
4574}
4575
4576int dmar_check_one_atsr(struct acpi_dmar_header *hdr, void *arg)
4577{
4578 int i;
4579 struct device *dev;
4580 struct acpi_dmar_atsr *atsr;
4581 struct dmar_atsr_unit *atsru;
4582
4583 atsr = container_of(hdr, struct acpi_dmar_atsr, header);
4584 atsru = dmar_find_atsr(atsr);
4585 if (!atsru)
4586 return 0;
4587
Linus Torvalds194dc872016-07-27 20:03:31 -07004588 if (!atsru->include_all && atsru->devices && atsru->devices_cnt) {
Jiang Liu6b197242014-11-09 22:47:58 +08004589 for_each_active_dev_scope(atsru->devices, atsru->devices_cnt,
4590 i, dev)
4591 return -EBUSY;
Linus Torvalds194dc872016-07-27 20:03:31 -07004592 }
Jiang Liu6b197242014-11-09 22:47:58 +08004593
4594 return 0;
4595}
4596
Jiang Liuffebeb42014-11-09 22:48:02 +08004597static int intel_iommu_add(struct dmar_drhd_unit *dmaru)
4598{
Bjorn Helgaase083ea5b2019-02-08 16:06:08 -06004599 int sp, ret;
Jiang Liuffebeb42014-11-09 22:48:02 +08004600 struct intel_iommu *iommu = dmaru->iommu;
4601
4602 if (g_iommus[iommu->seq_id])
4603 return 0;
4604
4605 if (hw_pass_through && !ecap_pass_through(iommu->ecap)) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02004606 pr_warn("%s: Doesn't support hardware pass through.\n",
Jiang Liuffebeb42014-11-09 22:48:02 +08004607 iommu->name);
4608 return -ENXIO;
4609 }
4610 if (!ecap_sc_support(iommu->ecap) &&
4611 domain_update_iommu_snooping(iommu)) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02004612 pr_warn("%s: Doesn't support snooping.\n",
Jiang Liuffebeb42014-11-09 22:48:02 +08004613 iommu->name);
4614 return -ENXIO;
4615 }
Lu Baolu64229e82020-01-02 08:18:20 +08004616 sp = domain_update_iommu_superpage(NULL, iommu) - 1;
Jiang Liuffebeb42014-11-09 22:48:02 +08004617 if (sp >= 0 && !(cap_super_page_val(iommu->cap) & (1 << sp))) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02004618 pr_warn("%s: Doesn't support large page.\n",
Jiang Liuffebeb42014-11-09 22:48:02 +08004619 iommu->name);
4620 return -ENXIO;
4621 }
4622
4623 /*
4624 * Disable translation if already enabled prior to OS handover.
4625 */
4626 if (iommu->gcmd & DMA_GCMD_TE)
4627 iommu_disable_translation(iommu);
4628
4629 g_iommus[iommu->seq_id] = iommu;
4630 ret = iommu_init_domains(iommu);
4631 if (ret == 0)
4632 ret = iommu_alloc_root_entry(iommu);
4633 if (ret)
4634 goto out;
4635
Jacob Panff3dc652020-01-02 08:18:03 +08004636 intel_svm_check(iommu);
David Woodhouse8a94ade2015-03-24 14:54:56 +00004637
Jiang Liuffebeb42014-11-09 22:48:02 +08004638 if (dmaru->ignored) {
4639 /*
4640 * we always have to disable PMRs or DMA may fail on this device
4641 */
4642 if (force_on)
4643 iommu_disable_protect_mem_regions(iommu);
4644 return 0;
4645 }
4646
4647 intel_iommu_init_qi(iommu);
4648 iommu_flush_write_buffer(iommu);
David Woodhousea222a7f2015-10-07 23:35:18 +01004649
4650#ifdef CONFIG_INTEL_IOMMU_SVM
Lu Baolu765b6a92018-12-10 09:58:55 +08004651 if (pasid_supported(iommu) && ecap_prs(iommu->ecap)) {
David Woodhousea222a7f2015-10-07 23:35:18 +01004652 ret = intel_svm_enable_prq(iommu);
4653 if (ret)
4654 goto disable_iommu;
4655 }
4656#endif
Jiang Liuffebeb42014-11-09 22:48:02 +08004657 ret = dmar_set_interrupt(iommu);
4658 if (ret)
4659 goto disable_iommu;
4660
4661 iommu_set_root_entry(iommu);
4662 iommu->flush.flush_context(iommu, 0, 0, 0, DMA_CCMD_GLOBAL_INVL);
4663 iommu->flush.flush_iotlb(iommu, 0, 0, 0, DMA_TLB_GLOBAL_FLUSH);
4664 iommu_enable_translation(iommu);
4665
Jiang Liuffebeb42014-11-09 22:48:02 +08004666 iommu_disable_protect_mem_regions(iommu);
4667 return 0;
4668
4669disable_iommu:
4670 disable_dmar_iommu(iommu);
4671out:
4672 free_dmar_iommu(iommu);
4673 return ret;
4674}
4675
Jiang Liu6b197242014-11-09 22:47:58 +08004676int dmar_iommu_hotplug(struct dmar_drhd_unit *dmaru, bool insert)
4677{
Jiang Liuffebeb42014-11-09 22:48:02 +08004678 int ret = 0;
4679 struct intel_iommu *iommu = dmaru->iommu;
4680
4681 if (!intel_iommu_enabled)
4682 return 0;
4683 if (iommu == NULL)
4684 return -EINVAL;
4685
4686 if (insert) {
4687 ret = intel_iommu_add(dmaru);
4688 } else {
4689 disable_dmar_iommu(iommu);
4690 free_dmar_iommu(iommu);
4691 }
4692
4693 return ret;
Jiang Liu6b197242014-11-09 22:47:58 +08004694}
4695
Jiang Liu9bdc5312014-01-06 14:18:27 +08004696static void intel_iommu_free_dmars(void)
4697{
4698 struct dmar_rmrr_unit *rmrru, *rmrr_n;
4699 struct dmar_atsr_unit *atsru, *atsr_n;
4700
4701 list_for_each_entry_safe(rmrru, rmrr_n, &dmar_rmrr_units, list) {
4702 list_del(&rmrru->list);
4703 dmar_free_dev_scope(&rmrru->devices, &rmrru->devices_cnt);
4704 kfree(rmrru);
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004705 }
4706
Jiang Liu9bdc5312014-01-06 14:18:27 +08004707 list_for_each_entry_safe(atsru, atsr_n, &dmar_atsr_units, list) {
4708 list_del(&atsru->list);
4709 intel_iommu_free_atsr(atsru);
4710 }
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004711}
4712
4713int dmar_find_matched_atsr_unit(struct pci_dev *dev)
4714{
Jiang Liub683b232014-02-19 14:07:32 +08004715 int i, ret = 1;
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004716 struct pci_bus *bus;
David Woodhouse832bd852014-03-07 15:08:36 +00004717 struct pci_dev *bridge = NULL;
4718 struct device *tmp;
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004719 struct acpi_dmar_atsr *atsr;
4720 struct dmar_atsr_unit *atsru;
4721
4722 dev = pci_physfn(dev);
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004723 for (bus = dev->bus; bus; bus = bus->parent) {
Jiang Liub5f82dd2014-02-19 14:07:31 +08004724 bridge = bus->self;
David Woodhoused14053b32015-10-15 09:28:06 +01004725 /* If it's an integrated device, allow ATS */
4726 if (!bridge)
4727 return 1;
4728 /* Connected via non-PCIe: no ATS */
4729 if (!pci_is_pcie(bridge) ||
Yijing Wang62f87c02012-07-24 17:20:03 +08004730 pci_pcie_type(bridge) == PCI_EXP_TYPE_PCI_BRIDGE)
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004731 return 0;
David Woodhoused14053b32015-10-15 09:28:06 +01004732 /* If we found the root port, look it up in the ATSR */
Jiang Liub5f82dd2014-02-19 14:07:31 +08004733 if (pci_pcie_type(bridge) == PCI_EXP_TYPE_ROOT_PORT)
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004734 break;
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004735 }
4736
Jiang Liu0e242612014-02-19 14:07:34 +08004737 rcu_read_lock();
Jiang Liub5f82dd2014-02-19 14:07:31 +08004738 list_for_each_entry_rcu(atsru, &dmar_atsr_units, list) {
4739 atsr = container_of(atsru->hdr, struct acpi_dmar_atsr, header);
4740 if (atsr->segment != pci_domain_nr(dev->bus))
4741 continue;
4742
Jiang Liub683b232014-02-19 14:07:32 +08004743 for_each_dev_scope(atsru->devices, atsru->devices_cnt, i, tmp)
David Woodhouse832bd852014-03-07 15:08:36 +00004744 if (tmp == &bridge->dev)
Jiang Liub683b232014-02-19 14:07:32 +08004745 goto out;
Jiang Liub5f82dd2014-02-19 14:07:31 +08004746
4747 if (atsru->include_all)
Jiang Liub683b232014-02-19 14:07:32 +08004748 goto out;
Jiang Liub5f82dd2014-02-19 14:07:31 +08004749 }
Jiang Liub683b232014-02-19 14:07:32 +08004750 ret = 0;
4751out:
Jiang Liu0e242612014-02-19 14:07:34 +08004752 rcu_read_unlock();
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004753
Jiang Liub683b232014-02-19 14:07:32 +08004754 return ret;
Suresh Siddha318fe7d2011-08-23 17:05:20 -07004755}
4756
Jiang Liu59ce0512014-02-19 14:07:35 +08004757int dmar_iommu_notify_scope_dev(struct dmar_pci_notify_info *info)
4758{
Bjorn Helgaase083ea5b2019-02-08 16:06:08 -06004759 int ret;
Jiang Liu59ce0512014-02-19 14:07:35 +08004760 struct dmar_rmrr_unit *rmrru;
4761 struct dmar_atsr_unit *atsru;
4762 struct acpi_dmar_atsr *atsr;
4763 struct acpi_dmar_reserved_memory *rmrr;
4764
Thomas Gleixnerb608fe32017-05-16 20:42:41 +02004765 if (!intel_iommu_enabled && system_state >= SYSTEM_RUNNING)
Jiang Liu59ce0512014-02-19 14:07:35 +08004766 return 0;
4767
4768 list_for_each_entry(rmrru, &dmar_rmrr_units, list) {
4769 rmrr = container_of(rmrru->hdr,
4770 struct acpi_dmar_reserved_memory, header);
4771 if (info->event == BUS_NOTIFY_ADD_DEVICE) {
4772 ret = dmar_insert_dev_scope(info, (void *)(rmrr + 1),
4773 ((void *)rmrr) + rmrr->header.length,
4774 rmrr->segment, rmrru->devices,
4775 rmrru->devices_cnt);
Bjorn Helgaase083ea5b2019-02-08 16:06:08 -06004776 if (ret < 0)
Jiang Liu59ce0512014-02-19 14:07:35 +08004777 return ret;
Joerg Roedele6a8c9b2016-02-29 23:49:47 +01004778 } else if (info->event == BUS_NOTIFY_REMOVED_DEVICE) {
Jiang Liu27e24952014-06-20 15:08:06 +08004779 dmar_remove_dev_scope(info, rmrr->segment,
4780 rmrru->devices, rmrru->devices_cnt);
Jiang Liu59ce0512014-02-19 14:07:35 +08004781 }
4782 }
4783
4784 list_for_each_entry(atsru, &dmar_atsr_units, list) {
4785 if (atsru->include_all)
4786 continue;
4787
4788 atsr = container_of(atsru->hdr, struct acpi_dmar_atsr, header);
4789 if (info->event == BUS_NOTIFY_ADD_DEVICE) {
4790 ret = dmar_insert_dev_scope(info, (void *)(atsr + 1),
4791 (void *)atsr + atsr->header.length,
4792 atsr->segment, atsru->devices,
4793 atsru->devices_cnt);
4794 if (ret > 0)
4795 break;
Bjorn Helgaase083ea5b2019-02-08 16:06:08 -06004796 else if (ret < 0)
Jiang Liu59ce0512014-02-19 14:07:35 +08004797 return ret;
Joerg Roedele6a8c9b2016-02-29 23:49:47 +01004798 } else if (info->event == BUS_NOTIFY_REMOVED_DEVICE) {
Jiang Liu59ce0512014-02-19 14:07:35 +08004799 if (dmar_remove_dev_scope(info, atsr->segment,
4800 atsru->devices, atsru->devices_cnt))
4801 break;
4802 }
4803 }
4804
4805 return 0;
4806}
4807
Jiang Liu75f05562014-02-19 14:07:37 +08004808static int intel_iommu_memory_notifier(struct notifier_block *nb,
4809 unsigned long val, void *v)
4810{
4811 struct memory_notify *mhp = v;
4812 unsigned long long start, end;
4813 unsigned long start_vpfn, last_vpfn;
4814
4815 switch (val) {
4816 case MEM_GOING_ONLINE:
4817 start = mhp->start_pfn << PAGE_SHIFT;
4818 end = ((mhp->start_pfn + mhp->nr_pages) << PAGE_SHIFT) - 1;
4819 if (iommu_domain_identity_map(si_domain, start, end)) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02004820 pr_warn("Failed to build identity map for [%llx-%llx]\n",
Jiang Liu75f05562014-02-19 14:07:37 +08004821 start, end);
4822 return NOTIFY_BAD;
4823 }
4824 break;
4825
4826 case MEM_OFFLINE:
4827 case MEM_CANCEL_ONLINE:
4828 start_vpfn = mm_to_dma_pfn(mhp->start_pfn);
4829 last_vpfn = mm_to_dma_pfn(mhp->start_pfn + mhp->nr_pages - 1);
4830 while (start_vpfn <= last_vpfn) {
4831 struct iova *iova;
4832 struct dmar_drhd_unit *drhd;
4833 struct intel_iommu *iommu;
David Woodhouseea8ea462014-03-05 17:09:32 +00004834 struct page *freelist;
Jiang Liu75f05562014-02-19 14:07:37 +08004835
4836 iova = find_iova(&si_domain->iovad, start_vpfn);
4837 if (iova == NULL) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02004838 pr_debug("Failed get IOVA for PFN %lx\n",
Jiang Liu75f05562014-02-19 14:07:37 +08004839 start_vpfn);
4840 break;
4841 }
4842
4843 iova = split_and_remove_iova(&si_domain->iovad, iova,
4844 start_vpfn, last_vpfn);
4845 if (iova == NULL) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02004846 pr_warn("Failed to split IOVA PFN [%lx-%lx]\n",
Jiang Liu75f05562014-02-19 14:07:37 +08004847 start_vpfn, last_vpfn);
4848 return NOTIFY_BAD;
4849 }
4850
David Woodhouseea8ea462014-03-05 17:09:32 +00004851 freelist = domain_unmap(si_domain, iova->pfn_lo,
4852 iova->pfn_hi);
4853
Jiang Liu75f05562014-02-19 14:07:37 +08004854 rcu_read_lock();
4855 for_each_active_iommu(iommu, drhd)
Joerg Roedela1ddcbe2015-07-21 15:20:32 +02004856 iommu_flush_iotlb_psi(iommu, si_domain,
Jiang Liua156ef92014-07-11 14:19:36 +08004857 iova->pfn_lo, iova_size(iova),
David Woodhouseea8ea462014-03-05 17:09:32 +00004858 !freelist, 0);
Jiang Liu75f05562014-02-19 14:07:37 +08004859 rcu_read_unlock();
David Woodhouseea8ea462014-03-05 17:09:32 +00004860 dma_free_pagelist(freelist);
Jiang Liu75f05562014-02-19 14:07:37 +08004861
4862 start_vpfn = iova->pfn_hi + 1;
4863 free_iova_mem(iova);
4864 }
4865 break;
4866 }
4867
4868 return NOTIFY_OK;
4869}
4870
4871static struct notifier_block intel_iommu_memory_nb = {
4872 .notifier_call = intel_iommu_memory_notifier,
4873 .priority = 0
4874};
4875
Omer Peleg22e2f9f2016-04-20 11:34:11 +03004876static void free_all_cpu_cached_iovas(unsigned int cpu)
4877{
4878 int i;
4879
4880 for (i = 0; i < g_num_of_iommus; i++) {
4881 struct intel_iommu *iommu = g_iommus[i];
4882 struct dmar_domain *domain;
Aaron Campbell0caa7612016-07-02 21:23:24 -03004883 int did;
Omer Peleg22e2f9f2016-04-20 11:34:11 +03004884
4885 if (!iommu)
4886 continue;
4887
Jan Niehusmann3bd4f912016-06-06 14:20:11 +02004888 for (did = 0; did < cap_ndoms(iommu->cap); did++) {
Aaron Campbell0caa7612016-07-02 21:23:24 -03004889 domain = get_iommu_domain(iommu, (u16)did);
Omer Peleg22e2f9f2016-04-20 11:34:11 +03004890
4891 if (!domain)
4892 continue;
4893 free_cpu_cached_iovas(cpu, &domain->iovad);
4894 }
4895 }
4896}
4897
Anna-Maria Gleixner21647612016-11-27 00:13:41 +01004898static int intel_iommu_cpu_dead(unsigned int cpu)
Omer Pelegaa473242016-04-20 11:33:02 +03004899{
Anna-Maria Gleixner21647612016-11-27 00:13:41 +01004900 free_all_cpu_cached_iovas(cpu);
Anna-Maria Gleixner21647612016-11-27 00:13:41 +01004901 return 0;
Omer Pelegaa473242016-04-20 11:33:02 +03004902}
4903
Joerg Roedel161b28a2017-03-28 17:04:52 +02004904static void intel_disable_iommus(void)
4905{
4906 struct intel_iommu *iommu = NULL;
4907 struct dmar_drhd_unit *drhd;
4908
4909 for_each_iommu(iommu, drhd)
4910 iommu_disable_translation(iommu);
4911}
4912
Deepa Dinamani6c3a44e2019-11-10 09:27:44 -08004913void intel_iommu_shutdown(void)
4914{
4915 struct dmar_drhd_unit *drhd;
4916 struct intel_iommu *iommu = NULL;
4917
4918 if (no_iommu || dmar_disabled)
4919 return;
4920
4921 down_write(&dmar_global_lock);
4922
4923 /* Disable PMRs explicitly here. */
4924 for_each_iommu(iommu, drhd)
4925 iommu_disable_protect_mem_regions(iommu);
4926
4927 /* Make sure the IOMMUs are switched off */
4928 intel_disable_iommus();
4929
4930 up_write(&dmar_global_lock);
4931}
4932
Joerg Roedela7fdb6e2017-02-28 13:57:18 +01004933static inline struct intel_iommu *dev_to_intel_iommu(struct device *dev)
4934{
Joerg Roedel2926a2aa2017-08-14 17:19:26 +02004935 struct iommu_device *iommu_dev = dev_to_iommu_device(dev);
4936
4937 return container_of(iommu_dev, struct intel_iommu, iommu);
Joerg Roedela7fdb6e2017-02-28 13:57:18 +01004938}
4939
Alex Williamsona5459cf2014-06-12 16:12:31 -06004940static ssize_t intel_iommu_show_version(struct device *dev,
4941 struct device_attribute *attr,
4942 char *buf)
4943{
Joerg Roedela7fdb6e2017-02-28 13:57:18 +01004944 struct intel_iommu *iommu = dev_to_intel_iommu(dev);
Alex Williamsona5459cf2014-06-12 16:12:31 -06004945 u32 ver = readl(iommu->reg + DMAR_VER_REG);
4946 return sprintf(buf, "%d:%d\n",
4947 DMAR_VER_MAJOR(ver), DMAR_VER_MINOR(ver));
4948}
4949static DEVICE_ATTR(version, S_IRUGO, intel_iommu_show_version, NULL);
4950
4951static ssize_t intel_iommu_show_address(struct device *dev,
4952 struct device_attribute *attr,
4953 char *buf)
4954{
Joerg Roedela7fdb6e2017-02-28 13:57:18 +01004955 struct intel_iommu *iommu = dev_to_intel_iommu(dev);
Alex Williamsona5459cf2014-06-12 16:12:31 -06004956 return sprintf(buf, "%llx\n", iommu->reg_phys);
4957}
4958static DEVICE_ATTR(address, S_IRUGO, intel_iommu_show_address, NULL);
4959
4960static ssize_t intel_iommu_show_cap(struct device *dev,
4961 struct device_attribute *attr,
4962 char *buf)
4963{
Joerg Roedela7fdb6e2017-02-28 13:57:18 +01004964 struct intel_iommu *iommu = dev_to_intel_iommu(dev);
Alex Williamsona5459cf2014-06-12 16:12:31 -06004965 return sprintf(buf, "%llx\n", iommu->cap);
4966}
4967static DEVICE_ATTR(cap, S_IRUGO, intel_iommu_show_cap, NULL);
4968
4969static ssize_t intel_iommu_show_ecap(struct device *dev,
4970 struct device_attribute *attr,
4971 char *buf)
4972{
Joerg Roedela7fdb6e2017-02-28 13:57:18 +01004973 struct intel_iommu *iommu = dev_to_intel_iommu(dev);
Alex Williamsona5459cf2014-06-12 16:12:31 -06004974 return sprintf(buf, "%llx\n", iommu->ecap);
4975}
4976static DEVICE_ATTR(ecap, S_IRUGO, intel_iommu_show_ecap, NULL);
4977
Alex Williamson2238c082015-07-14 15:24:53 -06004978static ssize_t intel_iommu_show_ndoms(struct device *dev,
4979 struct device_attribute *attr,
4980 char *buf)
4981{
Joerg Roedela7fdb6e2017-02-28 13:57:18 +01004982 struct intel_iommu *iommu = dev_to_intel_iommu(dev);
Alex Williamson2238c082015-07-14 15:24:53 -06004983 return sprintf(buf, "%ld\n", cap_ndoms(iommu->cap));
4984}
4985static DEVICE_ATTR(domains_supported, S_IRUGO, intel_iommu_show_ndoms, NULL);
4986
4987static ssize_t intel_iommu_show_ndoms_used(struct device *dev,
4988 struct device_attribute *attr,
4989 char *buf)
4990{
Joerg Roedela7fdb6e2017-02-28 13:57:18 +01004991 struct intel_iommu *iommu = dev_to_intel_iommu(dev);
Alex Williamson2238c082015-07-14 15:24:53 -06004992 return sprintf(buf, "%d\n", bitmap_weight(iommu->domain_ids,
4993 cap_ndoms(iommu->cap)));
4994}
4995static DEVICE_ATTR(domains_used, S_IRUGO, intel_iommu_show_ndoms_used, NULL);
4996
Alex Williamsona5459cf2014-06-12 16:12:31 -06004997static struct attribute *intel_iommu_attrs[] = {
4998 &dev_attr_version.attr,
4999 &dev_attr_address.attr,
5000 &dev_attr_cap.attr,
5001 &dev_attr_ecap.attr,
Alex Williamson2238c082015-07-14 15:24:53 -06005002 &dev_attr_domains_supported.attr,
5003 &dev_attr_domains_used.attr,
Alex Williamsona5459cf2014-06-12 16:12:31 -06005004 NULL,
5005};
5006
5007static struct attribute_group intel_iommu_group = {
5008 .name = "intel-iommu",
5009 .attrs = intel_iommu_attrs,
5010};
5011
5012const struct attribute_group *intel_iommu_groups[] = {
5013 &intel_iommu_group,
5014 NULL,
5015};
5016
Lu Baoluc5a5dc42019-09-06 14:14:50 +08005017static inline bool has_untrusted_dev(void)
Lu Baolu89a60792018-10-23 15:45:01 +08005018{
5019 struct pci_dev *pdev = NULL;
Lu Baolu89a60792018-10-23 15:45:01 +08005020
Lu Baoluc5a5dc42019-09-06 14:14:50 +08005021 for_each_pci_dev(pdev)
5022 if (pdev->untrusted)
5023 return true;
Lu Baolu89a60792018-10-23 15:45:01 +08005024
Lu Baoluc5a5dc42019-09-06 14:14:50 +08005025 return false;
5026}
Lu Baolu89a60792018-10-23 15:45:01 +08005027
Lu Baoluc5a5dc42019-09-06 14:14:50 +08005028static int __init platform_optin_force_iommu(void)
5029{
5030 if (!dmar_platform_optin() || no_platform_optin || !has_untrusted_dev())
Lu Baolu89a60792018-10-23 15:45:01 +08005031 return 0;
5032
5033 if (no_iommu || dmar_disabled)
5034 pr_info("Intel-IOMMU force enabled due to platform opt in\n");
5035
5036 /*
5037 * If Intel-IOMMU is disabled by default, we will apply identity
5038 * map for all devices except those marked as being untrusted.
5039 */
5040 if (dmar_disabled)
Lu Baolub89b6602020-01-15 11:03:59 +08005041 iommu_set_default_passthrough(false);
Lu Baolu89a60792018-10-23 15:45:01 +08005042
5043 dmar_disabled = 0;
Lu Baolu89a60792018-10-23 15:45:01 +08005044 no_iommu = 0;
5045
5046 return 1;
5047}
5048
Lu Baolufa212a92019-05-25 13:41:31 +08005049static int __init probe_acpi_namespace_devices(void)
5050{
5051 struct dmar_drhd_unit *drhd;
Qian Caiaf88ec32019-06-03 10:05:19 -04005052 /* To avoid a -Wunused-but-set-variable warning. */
5053 struct intel_iommu *iommu __maybe_unused;
Lu Baolufa212a92019-05-25 13:41:31 +08005054 struct device *dev;
5055 int i, ret = 0;
5056
5057 for_each_active_iommu(iommu, drhd) {
5058 for_each_active_dev_scope(drhd->devices,
5059 drhd->devices_cnt, i, dev) {
5060 struct acpi_device_physical_node *pn;
5061 struct iommu_group *group;
5062 struct acpi_device *adev;
5063
5064 if (dev->bus != &acpi_bus_type)
5065 continue;
5066
5067 adev = to_acpi_device(dev);
5068 mutex_lock(&adev->physical_node_lock);
5069 list_for_each_entry(pn,
5070 &adev->physical_node_list, node) {
5071 group = iommu_group_get(pn->dev);
5072 if (group) {
5073 iommu_group_put(group);
5074 continue;
5075 }
5076
5077 pn->dev->bus->iommu_ops = &intel_iommu_ops;
5078 ret = iommu_probe_device(pn->dev);
5079 if (ret)
5080 break;
5081 }
5082 mutex_unlock(&adev->physical_node_lock);
5083
5084 if (ret)
5085 return ret;
5086 }
5087 }
5088
5089 return 0;
5090}
5091
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07005092int __init intel_iommu_init(void)
5093{
Jiang Liu9bdc5312014-01-06 14:18:27 +08005094 int ret = -ENODEV;
Takao Indoh3a93c842013-04-23 17:35:03 +09005095 struct dmar_drhd_unit *drhd;
Jiang Liu7c919772014-01-06 14:18:18 +08005096 struct intel_iommu *iommu;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07005097
Lu Baolu89a60792018-10-23 15:45:01 +08005098 /*
5099 * Intel IOMMU is required for a TXT/tboot launch or platform
5100 * opt in, so enforce that.
5101 */
5102 force_on = tboot_force_iommu() || platform_optin_force_iommu();
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07005103
Jiang Liu3a5670e2014-02-19 14:07:33 +08005104 if (iommu_init_mempool()) {
5105 if (force_on)
5106 panic("tboot: Failed to initialize iommu memory\n");
5107 return -ENOMEM;
5108 }
5109
5110 down_write(&dmar_global_lock);
Joseph Cihulaa59b50e2009-06-30 19:31:10 -07005111 if (dmar_table_init()) {
5112 if (force_on)
5113 panic("tboot: Failed to initialize DMAR table\n");
Jiang Liu9bdc5312014-01-06 14:18:27 +08005114 goto out_free_dmar;
Joseph Cihulaa59b50e2009-06-30 19:31:10 -07005115 }
5116
Suresh Siddhac2c72862011-08-23 17:05:19 -07005117 if (dmar_dev_scope_init() < 0) {
Joseph Cihulaa59b50e2009-06-30 19:31:10 -07005118 if (force_on)
5119 panic("tboot: Failed to initialize DMAR device scope\n");
Jiang Liu9bdc5312014-01-06 14:18:27 +08005120 goto out_free_dmar;
Joseph Cihulaa59b50e2009-06-30 19:31:10 -07005121 }
Suresh Siddha1886e8a2008-07-10 11:16:37 -07005122
Joerg Roedelec154bf2017-10-06 15:00:53 +02005123 up_write(&dmar_global_lock);
5124
5125 /*
5126 * The bus notifier takes the dmar_global_lock, so lockdep will
5127 * complain later when we register it under the lock.
5128 */
5129 dmar_register_bus_notifier();
5130
5131 down_write(&dmar_global_lock);
5132
Joerg Roedel161b28a2017-03-28 17:04:52 +02005133 if (no_iommu || dmar_disabled) {
5134 /*
Shaohua Libfd20f12017-04-26 09:18:35 -07005135 * We exit the function here to ensure IOMMU's remapping and
5136 * mempool aren't setup, which means that the IOMMU's PMRs
5137 * won't be disabled via the call to init_dmars(). So disable
5138 * it explicitly here. The PMRs were setup by tboot prior to
5139 * calling SENTER, but the kernel is expected to reset/tear
5140 * down the PMRs.
5141 */
5142 if (intel_iommu_tboot_noforce) {
5143 for_each_iommu(iommu, drhd)
5144 iommu_disable_protect_mem_regions(iommu);
5145 }
5146
5147 /*
Joerg Roedel161b28a2017-03-28 17:04:52 +02005148 * Make sure the IOMMUs are switched off, even when we
5149 * boot into a kexec kernel and the previous kernel left
5150 * them enabled
5151 */
5152 intel_disable_iommus();
Jiang Liu9bdc5312014-01-06 14:18:27 +08005153 goto out_free_dmar;
Joerg Roedel161b28a2017-03-28 17:04:52 +02005154 }
Suresh Siddha2ae21012008-07-10 11:16:43 -07005155
Suresh Siddha318fe7d2011-08-23 17:05:20 -07005156 if (list_empty(&dmar_rmrr_units))
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02005157 pr_info("No RMRR found\n");
Suresh Siddha318fe7d2011-08-23 17:05:20 -07005158
5159 if (list_empty(&dmar_atsr_units))
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02005160 pr_info("No ATSR found\n");
Suresh Siddha318fe7d2011-08-23 17:05:20 -07005161
Joseph Cihula51a63e62011-03-21 11:04:24 -07005162 if (dmar_init_reserved_ranges()) {
5163 if (force_on)
5164 panic("tboot: Failed to reserve iommu ranges\n");
Jiang Liu3a5670e2014-02-19 14:07:33 +08005165 goto out_free_reserved_range;
Joseph Cihula51a63e62011-03-21 11:04:24 -07005166 }
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07005167
Lu Baolucf1ec452019-05-02 09:34:25 +08005168 if (dmar_map_gfx)
5169 intel_iommu_gfx_mapped = 1;
5170
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07005171 init_no_remapping_devices();
5172
Joseph Cihulab7792602011-05-03 00:08:37 -07005173 ret = init_dmars();
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07005174 if (ret) {
Joseph Cihulaa59b50e2009-06-30 19:31:10 -07005175 if (force_on)
5176 panic("tboot: Failed to initialize DMARs\n");
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02005177 pr_err("Initialization failed\n");
Jiang Liu9bdc5312014-01-06 14:18:27 +08005178 goto out_free_reserved_range;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07005179 }
Jiang Liu3a5670e2014-02-19 14:07:33 +08005180 up_write(&dmar_global_lock);
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07005181
Christoph Hellwig4fac8072017-12-24 13:57:08 +01005182#if defined(CONFIG_X86) && defined(CONFIG_SWIOTLB)
Lu Baoluc5a5dc42019-09-06 14:14:50 +08005183 /*
5184 * If the system has no untrusted device or the user has decided
5185 * to disable the bounce page mechanisms, we don't need swiotlb.
5186 * Mark this and the pre-allocated bounce pages will be released
5187 * later.
5188 */
5189 if (!has_untrusted_dev() || intel_no_bounce)
5190 swiotlb = 0;
FUJITA Tomonori75f1cdf2009-11-10 19:46:20 +09005191#endif
David Woodhouse19943b02009-08-04 16:19:20 +01005192 dma_ops = &intel_dma_ops;
Fenghua Yu4ed0d3e2009-04-24 17:30:20 -07005193
Rafael J. Wysocki134fac32011-03-23 22:16:14 +01005194 init_iommu_pm_ops();
Joerg Roedela8bcbb0d2008-12-03 15:14:02 +01005195
Joerg Roedel39ab9552017-02-01 16:56:46 +01005196 for_each_active_iommu(iommu, drhd) {
5197 iommu_device_sysfs_add(&iommu->iommu, NULL,
5198 intel_iommu_groups,
5199 "%s", iommu->name);
5200 iommu_device_set_ops(&iommu->iommu, &intel_iommu_ops);
5201 iommu_device_register(&iommu->iommu);
5202 }
Alex Williamsona5459cf2014-06-12 16:12:31 -06005203
Joerg Roedel4236d97d2011-09-06 17:56:07 +02005204 bus_set_iommu(&pci_bus_type, &intel_iommu_ops);
Jiang Liu75f05562014-02-19 14:07:37 +08005205 if (si_domain && !hw_pass_through)
5206 register_memory_notifier(&intel_iommu_memory_nb);
Anna-Maria Gleixner21647612016-11-27 00:13:41 +01005207 cpuhp_setup_state(CPUHP_IOMMU_INTEL_DEAD, "iommu/intel:dead", NULL,
5208 intel_iommu_cpu_dead);
Lu Baolud8190dc2019-05-25 13:41:25 +08005209
Lu Baolud5692d42019-06-12 08:28:49 +08005210 down_read(&dmar_global_lock);
Lu Baolufa212a92019-05-25 13:41:31 +08005211 if (probe_acpi_namespace_devices())
5212 pr_warn("ACPI name space devices didn't probe correctly\n");
Lu Baolud5692d42019-06-12 08:28:49 +08005213 up_read(&dmar_global_lock);
Lu Baolufa212a92019-05-25 13:41:31 +08005214
Lu Baolud8190dc2019-05-25 13:41:25 +08005215 /* Finally, we enable the DMA remapping hardware. */
5216 for_each_iommu(iommu, drhd) {
Lu Baolu6a8c6742019-06-12 08:28:47 +08005217 if (!drhd->ignored && !translation_pre_enabled(iommu))
Lu Baolud8190dc2019-05-25 13:41:25 +08005218 iommu_enable_translation(iommu);
5219
5220 iommu_disable_protect_mem_regions(iommu);
5221 }
5222 pr_info("Intel(R) Virtualization Technology for Directed I/O\n");
5223
Eugeni Dodonov8bc1f852011-11-23 16:42:14 -02005224 intel_iommu_enabled = 1;
Sohil Mehtaee2636b2018-09-11 17:11:38 -07005225 intel_iommu_debugfs_init();
Eugeni Dodonov8bc1f852011-11-23 16:42:14 -02005226
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07005227 return 0;
Jiang Liu9bdc5312014-01-06 14:18:27 +08005228
5229out_free_reserved_range:
5230 put_iova_domain(&reserved_iova_list);
Jiang Liu9bdc5312014-01-06 14:18:27 +08005231out_free_dmar:
5232 intel_iommu_free_dmars();
Jiang Liu3a5670e2014-02-19 14:07:33 +08005233 up_write(&dmar_global_lock);
5234 iommu_exit_mempool();
Jiang Liu9bdc5312014-01-06 14:18:27 +08005235 return ret;
Keshavamurthy, Anil Sba395922007-10-21 16:41:49 -07005236}
Keshavamurthy, Anil Se8204822007-10-21 16:41:55 -07005237
Lu Baolu0ce4a852019-08-26 16:50:56 +08005238static int domain_context_clear_one_cb(struct pci_dev *pdev, u16 alias, void *opaque)
5239{
5240 struct intel_iommu *iommu = opaque;
5241
5242 domain_context_clear_one(iommu, PCI_BUS_NUM(alias), alias & 0xff);
5243 return 0;
5244}
5245
5246/*
5247 * NB - intel-iommu lacks any sort of reference counting for the users of
5248 * dependent devices. If multiple endpoints have intersecting dependent
5249 * devices, unbinding the driver from any one of them will possibly leave
5250 * the others unable to operate.
5251 */
5252static void domain_context_clear(struct intel_iommu *iommu, struct device *dev)
5253{
5254 if (!iommu || !dev || !dev_is_pci(dev))
5255 return;
5256
5257 pci_for_each_dma_alias(to_pci_dev(dev), &domain_context_clear_one_cb, iommu);
5258}
5259
Joerg Roedel127c7612015-07-23 17:44:46 +02005260static void __dmar_remove_one_dev_info(struct device_domain_info *info)
Weidong Hanc7151a82008-12-08 22:51:37 +08005261{
Lu Baolu942067f2019-05-25 13:41:29 +08005262 struct dmar_domain *domain;
Weidong Hanc7151a82008-12-08 22:51:37 +08005263 struct intel_iommu *iommu;
5264 unsigned long flags;
Weidong Hanc7151a82008-12-08 22:51:37 +08005265
Joerg Roedel55d94042015-07-22 16:50:40 +02005266 assert_spin_locked(&device_domain_lock);
5267
Joerg Roedelb608ac32015-07-21 18:19:08 +02005268 if (WARN_ON(!info))
Weidong Hanc7151a82008-12-08 22:51:37 +08005269 return;
5270
Joerg Roedel127c7612015-07-23 17:44:46 +02005271 iommu = info->iommu;
Lu Baolu942067f2019-05-25 13:41:29 +08005272 domain = info->domain;
Joerg Roedel127c7612015-07-23 17:44:46 +02005273
5274 if (info->dev) {
Lu Baoluef848b72018-12-10 09:59:01 +08005275 if (dev_is_pci(info->dev) && sm_supported(iommu))
5276 intel_pasid_tear_down_entry(iommu, info->dev,
5277 PASID_RID2PASID);
5278
Joerg Roedel127c7612015-07-23 17:44:46 +02005279 iommu_disable_dev_iotlb(info);
Lu Baolu0ce4a852019-08-26 16:50:56 +08005280 domain_context_clear(iommu, info->dev);
Lu Baolua7fc93f2018-07-14 15:47:00 +08005281 intel_pasid_free_table(info->dev);
Joerg Roedel127c7612015-07-23 17:44:46 +02005282 }
5283
Joerg Roedelb608ac32015-07-21 18:19:08 +02005284 unlink_domain_info(info);
Roland Dreier3e7abe22011-07-20 06:22:21 -07005285
Joerg Roedeld160aca2015-07-22 11:52:53 +02005286 spin_lock_irqsave(&iommu->lock, flags);
Lu Baolu942067f2019-05-25 13:41:29 +08005287 domain_detach_iommu(domain, iommu);
Joerg Roedeld160aca2015-07-22 11:52:53 +02005288 spin_unlock_irqrestore(&iommu->lock, flags);
Joerg Roedel127c7612015-07-23 17:44:46 +02005289
Lu Baolu942067f2019-05-25 13:41:29 +08005290 /* free the private domain */
5291 if (domain->flags & DOMAIN_FLAG_LOSE_CHILDREN &&
Lu Baolu3a18844d2019-08-06 08:14:09 +08005292 !(domain->flags & DOMAIN_FLAG_STATIC_IDENTITY) &&
5293 list_empty(&domain->devices))
Lu Baolu942067f2019-05-25 13:41:29 +08005294 domain_exit(info->domain);
5295
Joerg Roedel127c7612015-07-23 17:44:46 +02005296 free_devinfo_mem(info);
Weidong Hanc7151a82008-12-08 22:51:37 +08005297}
5298
Bjorn Helgaas71753232019-02-08 16:06:15 -06005299static void dmar_remove_one_dev_info(struct device *dev)
Joerg Roedel55d94042015-07-22 16:50:40 +02005300{
Joerg Roedel127c7612015-07-23 17:44:46 +02005301 struct device_domain_info *info;
Joerg Roedel55d94042015-07-22 16:50:40 +02005302 unsigned long flags;
5303
Weidong Hanc7151a82008-12-08 22:51:37 +08005304 spin_lock_irqsave(&device_domain_lock, flags);
Joerg Roedel127c7612015-07-23 17:44:46 +02005305 info = dev->archdata.iommu;
Jerry Snitselaarbf708cf2020-01-21 17:34:26 -07005306 if (info && info != DEFER_DEVICE_DOMAIN_INFO
5307 && info != DUMMY_DEVICE_DOMAIN_INFO)
Lu Baoluae23bfb62019-08-06 08:14:08 +08005308 __dmar_remove_one_dev_info(info);
Weidong Han5e98c4b2008-12-08 23:03:27 +08005309 spin_unlock_irqrestore(&device_domain_lock, flags);
Weidong Han5e98c4b2008-12-08 23:03:27 +08005310}
5311
Joerg Roedel301e7ee2019-07-22 16:21:05 +02005312static int md_domain_init(struct dmar_domain *domain, int guest_width)
5313{
5314 int adjust_width;
5315
5316 init_iova_domain(&domain->iovad, VTD_PAGE_SIZE, IOVA_START_PFN);
5317 domain_reserve_special_ranges(domain);
5318
5319 /* calculate AGAW */
5320 domain->gaw = guest_width;
5321 adjust_width = guestwidth_to_adjustwidth(guest_width);
5322 domain->agaw = width_to_agaw(adjust_width);
5323
5324 domain->iommu_coherency = 0;
5325 domain->iommu_snooping = 0;
5326 domain->iommu_superpage = 0;
5327 domain->max_addr = 0;
5328
5329 /* always allocate the top pgd */
5330 domain->pgd = (struct dma_pte *)alloc_pgtable_page(domain->nid);
5331 if (!domain->pgd)
5332 return -ENOMEM;
5333 domain_flush_cache(domain, domain->pgd, PAGE_SIZE);
5334 return 0;
5335}
5336
Joerg Roedel00a77de2015-03-26 13:43:08 +01005337static struct iommu_domain *intel_iommu_domain_alloc(unsigned type)
Kay, Allen M38717942008-09-09 18:37:29 +03005338{
Joerg Roedel5d450802008-12-03 14:52:32 +01005339 struct dmar_domain *dmar_domain;
Joerg Roedel00a77de2015-03-26 13:43:08 +01005340 struct iommu_domain *domain;
Lu Baolu10f80082020-01-02 08:18:12 +08005341 int ret;
Joerg Roedel00a77de2015-03-26 13:43:08 +01005342
Lu Baolu4de354e2019-05-25 13:41:27 +08005343 switch (type) {
Lu Baolufa954e62019-05-25 13:41:28 +08005344 case IOMMU_DOMAIN_DMA:
5345 /* fallthrough */
Lu Baolu4de354e2019-05-25 13:41:27 +08005346 case IOMMU_DOMAIN_UNMANAGED:
Lu Baolufa954e62019-05-25 13:41:28 +08005347 dmar_domain = alloc_domain(0);
Lu Baolu4de354e2019-05-25 13:41:27 +08005348 if (!dmar_domain) {
5349 pr_err("Can't allocate dmar_domain\n");
5350 return NULL;
5351 }
Joerg Roedel301e7ee2019-07-22 16:21:05 +02005352 if (md_domain_init(dmar_domain, DEFAULT_DOMAIN_ADDRESS_WIDTH)) {
Lu Baolu4de354e2019-05-25 13:41:27 +08005353 pr_err("Domain initialization failed\n");
5354 domain_exit(dmar_domain);
5355 return NULL;
5356 }
Lu Baolufa954e62019-05-25 13:41:28 +08005357
Lu Baolu10f80082020-01-02 08:18:12 +08005358 if (!intel_iommu_strict && type == IOMMU_DOMAIN_DMA) {
5359 ret = init_iova_flush_queue(&dmar_domain->iovad,
5360 iommu_flush_iova,
5361 iova_entry_free);
Lu Baolu8e3391c2020-01-02 08:18:13 +08005362 if (ret)
5363 pr_info("iova flush queue initialization failed\n");
Lu Baolufa954e62019-05-25 13:41:28 +08005364 }
5365
Lu Baolu4de354e2019-05-25 13:41:27 +08005366 domain_update_iommu_cap(dmar_domain);
Kay, Allen M38717942008-09-09 18:37:29 +03005367
Lu Baolu4de354e2019-05-25 13:41:27 +08005368 domain = &dmar_domain->domain;
5369 domain->geometry.aperture_start = 0;
5370 domain->geometry.aperture_end =
5371 __DOMAIN_MAX_ADDR(dmar_domain->gaw);
5372 domain->geometry.force_aperture = true;
5373
5374 return domain;
5375 case IOMMU_DOMAIN_IDENTITY:
5376 return &si_domain->domain;
5377 default:
Joerg Roedel00a77de2015-03-26 13:43:08 +01005378 return NULL;
Kay, Allen M38717942008-09-09 18:37:29 +03005379 }
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08005380
Lu Baolu4de354e2019-05-25 13:41:27 +08005381 return NULL;
Kay, Allen M38717942008-09-09 18:37:29 +03005382}
Kay, Allen M38717942008-09-09 18:37:29 +03005383
Joerg Roedel00a77de2015-03-26 13:43:08 +01005384static void intel_iommu_domain_free(struct iommu_domain *domain)
Kay, Allen M38717942008-09-09 18:37:29 +03005385{
Lu Baolu4de354e2019-05-25 13:41:27 +08005386 if (domain != &si_domain->domain)
5387 domain_exit(to_dmar_domain(domain));
Kay, Allen M38717942008-09-09 18:37:29 +03005388}
Kay, Allen M38717942008-09-09 18:37:29 +03005389
Lu Baolu67b8e022019-03-25 09:30:32 +08005390/*
5391 * Check whether a @domain could be attached to the @dev through the
5392 * aux-domain attach/detach APIs.
5393 */
5394static inline bool
5395is_aux_domain(struct device *dev, struct iommu_domain *domain)
5396{
5397 struct device_domain_info *info = dev->archdata.iommu;
5398
5399 return info && info->auxd_enabled &&
5400 domain->type == IOMMU_DOMAIN_UNMANAGED;
5401}
5402
5403static void auxiliary_link_device(struct dmar_domain *domain,
5404 struct device *dev)
5405{
5406 struct device_domain_info *info = dev->archdata.iommu;
5407
5408 assert_spin_locked(&device_domain_lock);
5409 if (WARN_ON(!info))
5410 return;
5411
5412 domain->auxd_refcnt++;
5413 list_add(&domain->auxd, &info->auxiliary_domains);
5414}
5415
5416static void auxiliary_unlink_device(struct dmar_domain *domain,
5417 struct device *dev)
5418{
5419 struct device_domain_info *info = dev->archdata.iommu;
5420
5421 assert_spin_locked(&device_domain_lock);
5422 if (WARN_ON(!info))
5423 return;
5424
5425 list_del(&domain->auxd);
5426 domain->auxd_refcnt--;
5427
5428 if (!domain->auxd_refcnt && domain->default_pasid > 0)
Jacob Pan59a62332020-01-02 08:18:08 +08005429 ioasid_free(domain->default_pasid);
Lu Baolu67b8e022019-03-25 09:30:32 +08005430}
5431
5432static int aux_domain_add_dev(struct dmar_domain *domain,
5433 struct device *dev)
5434{
5435 int ret;
5436 u8 bus, devfn;
5437 unsigned long flags;
5438 struct intel_iommu *iommu;
5439
5440 iommu = device_to_iommu(dev, &bus, &devfn);
5441 if (!iommu)
5442 return -ENODEV;
5443
5444 if (domain->default_pasid <= 0) {
5445 int pasid;
5446
Jacob Pan59a62332020-01-02 08:18:08 +08005447 /* No private data needed for the default pasid */
5448 pasid = ioasid_alloc(NULL, PASID_MIN,
5449 pci_max_pasids(to_pci_dev(dev)) - 1,
5450 NULL);
5451 if (pasid == INVALID_IOASID) {
Lu Baolu67b8e022019-03-25 09:30:32 +08005452 pr_err("Can't allocate default pasid\n");
5453 return -ENODEV;
5454 }
5455 domain->default_pasid = pasid;
5456 }
5457
5458 spin_lock_irqsave(&device_domain_lock, flags);
5459 /*
5460 * iommu->lock must be held to attach domain to iommu and setup the
5461 * pasid entry for second level translation.
5462 */
5463 spin_lock(&iommu->lock);
5464 ret = domain_attach_iommu(domain, iommu);
5465 if (ret)
5466 goto attach_failed;
5467
5468 /* Setup the PASID entry for mediated devices: */
Lu Baoluddf09b62020-01-02 08:18:17 +08005469 if (domain_use_first_level(domain))
5470 ret = domain_setup_first_level(iommu, domain, dev,
5471 domain->default_pasid);
5472 else
5473 ret = intel_pasid_setup_second_level(iommu, domain, dev,
5474 domain->default_pasid);
Lu Baolu67b8e022019-03-25 09:30:32 +08005475 if (ret)
5476 goto table_failed;
5477 spin_unlock(&iommu->lock);
5478
5479 auxiliary_link_device(domain, dev);
5480
5481 spin_unlock_irqrestore(&device_domain_lock, flags);
5482
5483 return 0;
5484
5485table_failed:
5486 domain_detach_iommu(domain, iommu);
5487attach_failed:
5488 spin_unlock(&iommu->lock);
5489 spin_unlock_irqrestore(&device_domain_lock, flags);
5490 if (!domain->auxd_refcnt && domain->default_pasid > 0)
Jacob Pan59a62332020-01-02 08:18:08 +08005491 ioasid_free(domain->default_pasid);
Lu Baolu67b8e022019-03-25 09:30:32 +08005492
5493 return ret;
5494}
5495
5496static void aux_domain_remove_dev(struct dmar_domain *domain,
5497 struct device *dev)
5498{
5499 struct device_domain_info *info;
5500 struct intel_iommu *iommu;
5501 unsigned long flags;
5502
5503 if (!is_aux_domain(dev, &domain->domain))
5504 return;
5505
5506 spin_lock_irqsave(&device_domain_lock, flags);
5507 info = dev->archdata.iommu;
5508 iommu = info->iommu;
5509
5510 auxiliary_unlink_device(domain, dev);
5511
5512 spin_lock(&iommu->lock);
5513 intel_pasid_tear_down_entry(iommu, dev, domain->default_pasid);
5514 domain_detach_iommu(domain, iommu);
5515 spin_unlock(&iommu->lock);
5516
5517 spin_unlock_irqrestore(&device_domain_lock, flags);
5518}
5519
Lu Baolu8cc3759a2019-03-25 09:30:31 +08005520static int prepare_domain_attach_device(struct iommu_domain *domain,
5521 struct device *dev)
Kay, Allen M38717942008-09-09 18:37:29 +03005522{
Joerg Roedel00a77de2015-03-26 13:43:08 +01005523 struct dmar_domain *dmar_domain = to_dmar_domain(domain);
Weidong Hanfe40f1e2008-12-08 23:10:23 +08005524 struct intel_iommu *iommu;
5525 int addr_width;
David Woodhouse156baca2014-03-09 14:00:57 -07005526 u8 bus, devfn;
Kay, Allen M38717942008-09-09 18:37:29 +03005527
David Woodhouse156baca2014-03-09 14:00:57 -07005528 iommu = device_to_iommu(dev, &bus, &devfn);
Weidong Hanfe40f1e2008-12-08 23:10:23 +08005529 if (!iommu)
5530 return -ENODEV;
5531
5532 /* check if this iommu agaw is sufficient for max mapped address */
5533 addr_width = agaw_to_width(iommu->agaw);
Tom Lyona99c47a2010-05-17 08:20:45 +01005534 if (addr_width > cap_mgaw(iommu->cap))
5535 addr_width = cap_mgaw(iommu->cap);
5536
5537 if (dmar_domain->max_addr > (1LL << addr_width)) {
Bjorn Helgaas932a6522019-02-08 16:06:00 -06005538 dev_err(dev, "%s: iommu width (%d) is not "
5539 "sufficient for the mapped address (%llx)\n",
5540 __func__, addr_width, dmar_domain->max_addr);
Weidong Hanfe40f1e2008-12-08 23:10:23 +08005541 return -EFAULT;
5542 }
Tom Lyona99c47a2010-05-17 08:20:45 +01005543 dmar_domain->gaw = addr_width;
5544
5545 /*
5546 * Knock out extra levels of page tables if necessary
5547 */
5548 while (iommu->agaw < dmar_domain->agaw) {
5549 struct dma_pte *pte;
5550
5551 pte = dmar_domain->pgd;
5552 if (dma_pte_present(pte)) {
Sheng Yang25cbff12010-06-12 19:21:42 +08005553 dmar_domain->pgd = (struct dma_pte *)
5554 phys_to_virt(dma_pte_addr(pte));
Jan Kiszka7a661012010-11-02 08:05:51 +01005555 free_pgtable_page(pte);
Tom Lyona99c47a2010-05-17 08:20:45 +01005556 }
5557 dmar_domain->agaw--;
5558 }
Weidong Hanfe40f1e2008-12-08 23:10:23 +08005559
Lu Baolu8cc3759a2019-03-25 09:30:31 +08005560 return 0;
5561}
5562
5563static int intel_iommu_attach_device(struct iommu_domain *domain,
5564 struct device *dev)
5565{
5566 int ret;
5567
Lu Baolu56795822019-06-12 08:28:48 +08005568 if (domain->type == IOMMU_DOMAIN_UNMANAGED &&
5569 device_is_rmrr_locked(dev)) {
Lu Baolu8cc3759a2019-03-25 09:30:31 +08005570 dev_warn(dev, "Device is ineligible for IOMMU domain attach due to platform RMRR requirement. Contact your platform vendor.\n");
5571 return -EPERM;
5572 }
5573
Lu Baolu67b8e022019-03-25 09:30:32 +08005574 if (is_aux_domain(dev, domain))
5575 return -EPERM;
5576
Lu Baolu8cc3759a2019-03-25 09:30:31 +08005577 /* normally dev is not mapped */
5578 if (unlikely(domain_context_mapped(dev))) {
5579 struct dmar_domain *old_domain;
5580
5581 old_domain = find_domain(dev);
Lu Baolufa954e62019-05-25 13:41:28 +08005582 if (old_domain)
Lu Baolu8cc3759a2019-03-25 09:30:31 +08005583 dmar_remove_one_dev_info(dev);
Lu Baolu8cc3759a2019-03-25 09:30:31 +08005584 }
5585
5586 ret = prepare_domain_attach_device(domain, dev);
5587 if (ret)
5588 return ret;
5589
5590 return domain_add_dev_info(to_dmar_domain(domain), dev);
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08005591}
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08005592
Lu Baolu67b8e022019-03-25 09:30:32 +08005593static int intel_iommu_aux_attach_device(struct iommu_domain *domain,
5594 struct device *dev)
5595{
5596 int ret;
5597
5598 if (!is_aux_domain(dev, domain))
5599 return -EPERM;
5600
5601 ret = prepare_domain_attach_device(domain, dev);
5602 if (ret)
5603 return ret;
5604
5605 return aux_domain_add_dev(to_dmar_domain(domain), dev);
5606}
5607
Joerg Roedel4c5478c2008-12-03 14:58:24 +01005608static void intel_iommu_detach_device(struct iommu_domain *domain,
5609 struct device *dev)
Kay, Allen M38717942008-09-09 18:37:29 +03005610{
Bjorn Helgaas71753232019-02-08 16:06:15 -06005611 dmar_remove_one_dev_info(dev);
Kay, Allen M38717942008-09-09 18:37:29 +03005612}
Kay, Allen M38717942008-09-09 18:37:29 +03005613
Lu Baolu67b8e022019-03-25 09:30:32 +08005614static void intel_iommu_aux_detach_device(struct iommu_domain *domain,
5615 struct device *dev)
5616{
5617 aux_domain_remove_dev(to_dmar_domain(domain), dev);
5618}
5619
Joerg Roedelb146a1c9f2010-01-20 17:17:37 +01005620static int intel_iommu_map(struct iommu_domain *domain,
5621 unsigned long iova, phys_addr_t hpa,
Tom Murphy781ca2d2019-09-08 09:56:38 -07005622 size_t size, int iommu_prot, gfp_t gfp)
Kay, Allen M38717942008-09-09 18:37:29 +03005623{
Joerg Roedel00a77de2015-03-26 13:43:08 +01005624 struct dmar_domain *dmar_domain = to_dmar_domain(domain);
Weidong Hanfe40f1e2008-12-08 23:10:23 +08005625 u64 max_addr;
Joerg Roedeldde57a22008-12-03 15:04:09 +01005626 int prot = 0;
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08005627 int ret;
Weidong Hanfe40f1e2008-12-08 23:10:23 +08005628
Joerg Roedeldde57a22008-12-03 15:04:09 +01005629 if (iommu_prot & IOMMU_READ)
5630 prot |= DMA_PTE_READ;
5631 if (iommu_prot & IOMMU_WRITE)
5632 prot |= DMA_PTE_WRITE;
Sheng Yang9cf06692009-03-18 15:33:07 +08005633 if ((iommu_prot & IOMMU_CACHE) && dmar_domain->iommu_snooping)
5634 prot |= DMA_PTE_SNP;
Joerg Roedeldde57a22008-12-03 15:04:09 +01005635
David Woodhouse163cc522009-06-28 00:51:17 +01005636 max_addr = iova + size;
Joerg Roedeldde57a22008-12-03 15:04:09 +01005637 if (dmar_domain->max_addr < max_addr) {
Weidong Hanfe40f1e2008-12-08 23:10:23 +08005638 u64 end;
5639
5640 /* check if minimum agaw is sufficient for mapped address */
Tom Lyon8954da12010-05-17 08:19:52 +01005641 end = __DOMAIN_MAX_ADDR(dmar_domain->gaw) + 1;
Weidong Hanfe40f1e2008-12-08 23:10:23 +08005642 if (end < max_addr) {
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02005643 pr_err("%s: iommu width (%d) is not "
Weidong Hanfe40f1e2008-12-08 23:10:23 +08005644 "sufficient for the mapped address (%llx)\n",
Tom Lyon8954da12010-05-17 08:19:52 +01005645 __func__, dmar_domain->gaw, max_addr);
Weidong Hanfe40f1e2008-12-08 23:10:23 +08005646 return -EFAULT;
5647 }
Joerg Roedeldde57a22008-12-03 15:04:09 +01005648 dmar_domain->max_addr = max_addr;
Weidong Hanfe40f1e2008-12-08 23:10:23 +08005649 }
David Woodhousead051222009-06-28 14:22:28 +01005650 /* Round up size to next multiple of PAGE_SIZE, if it and
5651 the low bits of hpa would take us onto the next page */
David Woodhouse88cb6a72009-06-28 15:03:06 +01005652 size = aligned_nrpages(hpa, size);
David Woodhousead051222009-06-28 14:22:28 +01005653 ret = domain_pfn_mapping(dmar_domain, iova >> VTD_PAGE_SHIFT,
5654 hpa >> VTD_PAGE_SHIFT, size, prot);
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08005655 return ret;
Kay, Allen M38717942008-09-09 18:37:29 +03005656}
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08005657
Ohad Ben-Cohen50090652011-11-10 11:32:25 +02005658static size_t intel_iommu_unmap(struct iommu_domain *domain,
Will Deacon56f8af52019-07-02 16:44:06 +01005659 unsigned long iova, size_t size,
5660 struct iommu_iotlb_gather *gather)
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08005661{
Joerg Roedel00a77de2015-03-26 13:43:08 +01005662 struct dmar_domain *dmar_domain = to_dmar_domain(domain);
David Woodhouseea8ea462014-03-05 17:09:32 +00005663 struct page *freelist = NULL;
David Woodhouseea8ea462014-03-05 17:09:32 +00005664 unsigned long start_pfn, last_pfn;
5665 unsigned int npages;
Joerg Roedel42e8c182015-07-21 15:50:02 +02005666 int iommu_id, level = 0;
Sheng Yang4b99d352009-07-08 11:52:52 +01005667
David Woodhouse5cf0a762014-03-19 16:07:49 +00005668 /* Cope with horrid API which requires us to unmap more than the
5669 size argument if it happens to be a large-page mapping. */
Joerg Roedeldc02e462015-08-13 11:15:13 +02005670 BUG_ON(!pfn_to_dma_pte(dmar_domain, iova >> VTD_PAGE_SHIFT, &level));
David Woodhouse5cf0a762014-03-19 16:07:49 +00005671
5672 if (size < VTD_PAGE_SIZE << level_to_offset_bits(level))
5673 size = VTD_PAGE_SIZE << level_to_offset_bits(level);
5674
David Woodhouseea8ea462014-03-05 17:09:32 +00005675 start_pfn = iova >> VTD_PAGE_SHIFT;
5676 last_pfn = (iova + size - 1) >> VTD_PAGE_SHIFT;
5677
5678 freelist = domain_unmap(dmar_domain, start_pfn, last_pfn);
5679
5680 npages = last_pfn - start_pfn + 1;
5681
Shaokun Zhangf746a022018-03-22 18:18:06 +08005682 for_each_domain_iommu(iommu_id, dmar_domain)
Joerg Roedel42e8c182015-07-21 15:50:02 +02005683 iommu_flush_iotlb_psi(g_iommus[iommu_id], dmar_domain,
5684 start_pfn, npages, !freelist, 0);
David Woodhouseea8ea462014-03-05 17:09:32 +00005685
5686 dma_free_pagelist(freelist);
Weidong Hanfe40f1e2008-12-08 23:10:23 +08005687
David Woodhouse163cc522009-06-28 00:51:17 +01005688 if (dmar_domain->max_addr == iova + size)
5689 dmar_domain->max_addr = iova;
Joerg Roedelb146a1c9f2010-01-20 17:17:37 +01005690
David Woodhouse5cf0a762014-03-19 16:07:49 +00005691 return size;
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08005692}
Kay, Allen M38717942008-09-09 18:37:29 +03005693
Joerg Roedeld14d6572008-12-03 15:06:57 +01005694static phys_addr_t intel_iommu_iova_to_phys(struct iommu_domain *domain,
Varun Sethibb5547a2013-03-29 01:23:58 +05305695 dma_addr_t iova)
Kay, Allen M38717942008-09-09 18:37:29 +03005696{
Joerg Roedel00a77de2015-03-26 13:43:08 +01005697 struct dmar_domain *dmar_domain = to_dmar_domain(domain);
Kay, Allen M38717942008-09-09 18:37:29 +03005698 struct dma_pte *pte;
David Woodhouse5cf0a762014-03-19 16:07:49 +00005699 int level = 0;
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08005700 u64 phys = 0;
Kay, Allen M38717942008-09-09 18:37:29 +03005701
David Woodhouse5cf0a762014-03-19 16:07:49 +00005702 pte = pfn_to_dma_pte(dmar_domain, iova >> VTD_PAGE_SHIFT, &level);
Kay, Allen M38717942008-09-09 18:37:29 +03005703 if (pte)
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08005704 phys = dma_pte_addr(pte);
Kay, Allen M38717942008-09-09 18:37:29 +03005705
Weidong Hanfaa3d6f2008-12-08 23:09:29 +08005706 return phys;
Kay, Allen M38717942008-09-09 18:37:29 +03005707}
Joerg Roedela8bcbb0d2008-12-03 15:14:02 +01005708
Lu Baolu95587a72019-03-25 09:30:30 +08005709static inline bool scalable_mode_support(void)
5710{
5711 struct dmar_drhd_unit *drhd;
5712 struct intel_iommu *iommu;
5713 bool ret = true;
5714
5715 rcu_read_lock();
5716 for_each_active_iommu(iommu, drhd) {
5717 if (!sm_supported(iommu)) {
5718 ret = false;
5719 break;
5720 }
5721 }
5722 rcu_read_unlock();
5723
5724 return ret;
5725}
5726
5727static inline bool iommu_pasid_support(void)
5728{
5729 struct dmar_drhd_unit *drhd;
5730 struct intel_iommu *iommu;
5731 bool ret = true;
5732
5733 rcu_read_lock();
5734 for_each_active_iommu(iommu, drhd) {
5735 if (!pasid_supported(iommu)) {
5736 ret = false;
5737 break;
5738 }
5739 }
5740 rcu_read_unlock();
5741
5742 return ret;
5743}
5744
Lu Baolu2cd13112020-01-02 08:18:15 +08005745static inline bool nested_mode_support(void)
5746{
5747 struct dmar_drhd_unit *drhd;
5748 struct intel_iommu *iommu;
5749 bool ret = true;
5750
5751 rcu_read_lock();
5752 for_each_active_iommu(iommu, drhd) {
5753 if (!sm_supported(iommu) || !ecap_nest(iommu->ecap)) {
5754 ret = false;
5755 break;
5756 }
5757 }
5758 rcu_read_unlock();
5759
5760 return ret;
5761}
5762
Joerg Roedel5d587b82014-09-05 10:50:45 +02005763static bool intel_iommu_capable(enum iommu_cap cap)
Sheng Yangdbb9fd82009-03-18 15:33:06 +08005764{
Sheng Yangdbb9fd82009-03-18 15:33:06 +08005765 if (cap == IOMMU_CAP_CACHE_COHERENCY)
Joerg Roedel5d587b82014-09-05 10:50:45 +02005766 return domain_update_iommu_snooping(NULL) == 1;
Tom Lyon323f99c2010-07-02 16:56:14 -04005767 if (cap == IOMMU_CAP_INTR_REMAP)
Joerg Roedel5d587b82014-09-05 10:50:45 +02005768 return irq_remapping_enabled == 1;
Sheng Yangdbb9fd82009-03-18 15:33:06 +08005769
Joerg Roedel5d587b82014-09-05 10:50:45 +02005770 return false;
Sheng Yangdbb9fd82009-03-18 15:33:06 +08005771}
5772
Alex Williamsonabdfdde2012-05-30 14:19:19 -06005773static int intel_iommu_add_device(struct device *dev)
Alex Williamson70ae6f02011-10-21 15:56:11 -04005774{
Lu Baolu942067f2019-05-25 13:41:29 +08005775 struct dmar_domain *dmar_domain;
5776 struct iommu_domain *domain;
Alex Williamsona5459cf2014-06-12 16:12:31 -06005777 struct intel_iommu *iommu;
Alex Williamsonabdfdde2012-05-30 14:19:19 -06005778 struct iommu_group *group;
David Woodhouse156baca2014-03-09 14:00:57 -07005779 u8 bus, devfn;
Lu Baolu942067f2019-05-25 13:41:29 +08005780 int ret;
Alex Williamson70ae6f02011-10-21 15:56:11 -04005781
Alex Williamsona5459cf2014-06-12 16:12:31 -06005782 iommu = device_to_iommu(dev, &bus, &devfn);
5783 if (!iommu)
Alex Williamson70ae6f02011-10-21 15:56:11 -04005784 return -ENODEV;
5785
Joerg Roedele3d10af2017-02-01 17:23:22 +01005786 iommu_device_link(&iommu->iommu, dev);
Alex Williamsonabdfdde2012-05-30 14:19:19 -06005787
Lu Baolu8af46c72019-05-25 13:41:32 +08005788 if (translation_pre_enabled(iommu))
5789 dev->archdata.iommu = DEFER_DEVICE_DOMAIN_INFO;
5790
Alex Williamsone17f9ff2014-07-03 09:51:37 -06005791 group = iommu_group_get_for_dev(dev);
Alex Williamson783f1572012-05-30 14:19:43 -06005792
Jon Derrickf78947c2019-12-31 13:24:20 -07005793 if (IS_ERR(group)) {
5794 ret = PTR_ERR(group);
5795 goto unlink;
5796 }
Alex Williamson70ae6f02011-10-21 15:56:11 -04005797
Alex Williamsonabdfdde2012-05-30 14:19:19 -06005798 iommu_group_put(group);
Lu Baolu942067f2019-05-25 13:41:29 +08005799
5800 domain = iommu_get_domain_for_dev(dev);
5801 dmar_domain = to_dmar_domain(domain);
5802 if (domain->type == IOMMU_DOMAIN_DMA) {
Lu Baolu0e31a722019-05-25 13:41:34 +08005803 if (device_def_domain_type(dev) == IOMMU_DOMAIN_IDENTITY) {
Lu Baolu942067f2019-05-25 13:41:29 +08005804 ret = iommu_request_dm_for_dev(dev);
5805 if (ret) {
Lu Baoluae23bfb62019-08-06 08:14:08 +08005806 dmar_remove_one_dev_info(dev);
Lu Baolu942067f2019-05-25 13:41:29 +08005807 dmar_domain->flags |= DOMAIN_FLAG_LOSE_CHILDREN;
5808 domain_add_dev_info(si_domain, dev);
5809 dev_info(dev,
5810 "Device uses a private identity domain.\n");
Lu Baolu942067f2019-05-25 13:41:29 +08005811 }
Lu Baolu942067f2019-05-25 13:41:29 +08005812 }
5813 } else {
Lu Baolu0e31a722019-05-25 13:41:34 +08005814 if (device_def_domain_type(dev) == IOMMU_DOMAIN_DMA) {
Lu Baolu942067f2019-05-25 13:41:29 +08005815 ret = iommu_request_dma_domain_for_dev(dev);
5816 if (ret) {
Lu Baoluae23bfb62019-08-06 08:14:08 +08005817 dmar_remove_one_dev_info(dev);
Lu Baolu942067f2019-05-25 13:41:29 +08005818 dmar_domain->flags |= DOMAIN_FLAG_LOSE_CHILDREN;
Lu Baolu4ec066c2019-05-25 13:41:33 +08005819 if (!get_private_domain_for_dev(dev)) {
Lu Baolu942067f2019-05-25 13:41:29 +08005820 dev_warn(dev,
5821 "Failed to get a private domain.\n");
Jon Derrickf78947c2019-12-31 13:24:20 -07005822 ret = -ENOMEM;
5823 goto unlink;
Lu Baolu942067f2019-05-25 13:41:29 +08005824 }
5825
5826 dev_info(dev,
5827 "Device uses a private dma domain.\n");
Lu Baolu942067f2019-05-25 13:41:29 +08005828 }
Lu Baolu942067f2019-05-25 13:41:29 +08005829 }
5830 }
5831
Lu Baolucfb94a32019-09-06 14:14:52 +08005832 if (device_needs_bounce(dev)) {
5833 dev_info(dev, "Use Intel IOMMU bounce page dma_ops\n");
5834 set_dma_ops(dev, &bounce_dma_ops);
5835 }
5836
Alex Williamsone17f9ff2014-07-03 09:51:37 -06005837 return 0;
Jon Derrickf78947c2019-12-31 13:24:20 -07005838
5839unlink:
5840 iommu_device_unlink(&iommu->iommu, dev);
5841 return ret;
Alex Williamsonabdfdde2012-05-30 14:19:19 -06005842}
5843
5844static void intel_iommu_remove_device(struct device *dev)
5845{
Alex Williamsona5459cf2014-06-12 16:12:31 -06005846 struct intel_iommu *iommu;
5847 u8 bus, devfn;
5848
5849 iommu = device_to_iommu(dev, &bus, &devfn);
5850 if (!iommu)
5851 return;
5852
Lu Baolu458b7c82019-08-01 11:14:58 +08005853 dmar_remove_one_dev_info(dev);
5854
Alex Williamsonabdfdde2012-05-30 14:19:19 -06005855 iommu_group_remove_device(dev);
Alex Williamsona5459cf2014-06-12 16:12:31 -06005856
Joerg Roedele3d10af2017-02-01 17:23:22 +01005857 iommu_device_unlink(&iommu->iommu, dev);
Lu Baolucfb94a32019-09-06 14:14:52 +08005858
5859 if (device_needs_bounce(dev))
5860 set_dma_ops(dev, NULL);
Alex Williamson70ae6f02011-10-21 15:56:11 -04005861}
5862
Eric Auger0659b8d2017-01-19 20:57:53 +00005863static void intel_iommu_get_resv_regions(struct device *device,
5864 struct list_head *head)
5865{
Eric Auger5f64ce52019-06-03 08:53:31 +02005866 int prot = DMA_PTE_READ | DMA_PTE_WRITE;
Eric Auger0659b8d2017-01-19 20:57:53 +00005867 struct iommu_resv_region *reg;
5868 struct dmar_rmrr_unit *rmrr;
5869 struct device *i_dev;
5870 int i;
5871
Eric Auger5f64ce52019-06-03 08:53:31 +02005872 down_read(&dmar_global_lock);
Eric Auger0659b8d2017-01-19 20:57:53 +00005873 for_each_rmrr_units(rmrr) {
5874 for_each_active_dev_scope(rmrr->devices, rmrr->devices_cnt,
5875 i, i_dev) {
Eric Auger5f64ce52019-06-03 08:53:31 +02005876 struct iommu_resv_region *resv;
Eric Auger1c5c59f2019-06-03 08:53:36 +02005877 enum iommu_resv_type type;
Eric Auger5f64ce52019-06-03 08:53:31 +02005878 size_t length;
5879
Eric Auger3855ba22019-06-03 08:53:34 +02005880 if (i_dev != device &&
5881 !is_downstream_to_pci_bridge(device, i_dev))
Eric Auger0659b8d2017-01-19 20:57:53 +00005882 continue;
5883
Eric Auger5f64ce52019-06-03 08:53:31 +02005884 length = rmrr->end_address - rmrr->base_address + 1;
Eric Auger1c5c59f2019-06-03 08:53:36 +02005885
5886 type = device_rmrr_is_relaxable(device) ?
5887 IOMMU_RESV_DIRECT_RELAXABLE : IOMMU_RESV_DIRECT;
5888
Eric Auger5f64ce52019-06-03 08:53:31 +02005889 resv = iommu_alloc_resv_region(rmrr->base_address,
Eric Auger1c5c59f2019-06-03 08:53:36 +02005890 length, prot, type);
Eric Auger5f64ce52019-06-03 08:53:31 +02005891 if (!resv)
5892 break;
5893
5894 list_add_tail(&resv->list, head);
Eric Auger0659b8d2017-01-19 20:57:53 +00005895 }
5896 }
Eric Auger5f64ce52019-06-03 08:53:31 +02005897 up_read(&dmar_global_lock);
Eric Auger0659b8d2017-01-19 20:57:53 +00005898
Lu Baolud850c2e2019-05-25 13:41:24 +08005899#ifdef CONFIG_INTEL_IOMMU_FLOPPY_WA
5900 if (dev_is_pci(device)) {
5901 struct pci_dev *pdev = to_pci_dev(device);
5902
5903 if ((pdev->class >> 8) == PCI_CLASS_BRIDGE_ISA) {
Jerry Snitselaarcde93192019-12-12 22:36:42 -07005904 reg = iommu_alloc_resv_region(0, 1UL << 24, prot,
Alex Williamsond8018a02019-12-11 13:28:29 -07005905 IOMMU_RESV_DIRECT_RELAXABLE);
Lu Baolud850c2e2019-05-25 13:41:24 +08005906 if (reg)
5907 list_add_tail(&reg->list, head);
5908 }
5909 }
5910#endif /* CONFIG_INTEL_IOMMU_FLOPPY_WA */
5911
Eric Auger0659b8d2017-01-19 20:57:53 +00005912 reg = iommu_alloc_resv_region(IOAPIC_RANGE_START,
5913 IOAPIC_RANGE_END - IOAPIC_RANGE_START + 1,
Robin Murphy9d3a4de2017-03-16 17:00:16 +00005914 0, IOMMU_RESV_MSI);
Eric Auger0659b8d2017-01-19 20:57:53 +00005915 if (!reg)
5916 return;
5917 list_add_tail(&reg->list, head);
5918}
5919
Lu Baolud7cbc0f2019-03-25 09:30:29 +08005920int intel_iommu_enable_pasid(struct intel_iommu *iommu, struct device *dev)
David Woodhouse2f26e0a2015-09-09 11:40:47 +01005921{
5922 struct device_domain_info *info;
5923 struct context_entry *context;
5924 struct dmar_domain *domain;
5925 unsigned long flags;
5926 u64 ctx_lo;
5927 int ret;
5928
Lu Baolu4ec066c2019-05-25 13:41:33 +08005929 domain = find_domain(dev);
David Woodhouse2f26e0a2015-09-09 11:40:47 +01005930 if (!domain)
5931 return -EINVAL;
5932
5933 spin_lock_irqsave(&device_domain_lock, flags);
5934 spin_lock(&iommu->lock);
5935
5936 ret = -EINVAL;
Lu Baolud7cbc0f2019-03-25 09:30:29 +08005937 info = dev->archdata.iommu;
David Woodhouse2f26e0a2015-09-09 11:40:47 +01005938 if (!info || !info->pasid_supported)
5939 goto out;
5940
5941 context = iommu_context_addr(iommu, info->bus, info->devfn, 0);
5942 if (WARN_ON(!context))
5943 goto out;
5944
5945 ctx_lo = context[0].lo;
5946
David Woodhouse2f26e0a2015-09-09 11:40:47 +01005947 if (!(ctx_lo & CONTEXT_PASIDE)) {
David Woodhouse2f26e0a2015-09-09 11:40:47 +01005948 ctx_lo |= CONTEXT_PASIDE;
5949 context[0].lo = ctx_lo;
5950 wmb();
Lu Baolud7cbc0f2019-03-25 09:30:29 +08005951 iommu->flush.flush_context(iommu,
5952 domain->iommu_did[iommu->seq_id],
5953 PCI_DEVID(info->bus, info->devfn),
David Woodhouse2f26e0a2015-09-09 11:40:47 +01005954 DMA_CCMD_MASK_NOBIT,
5955 DMA_CCMD_DEVICE_INVL);
5956 }
5957
5958 /* Enable PASID support in the device, if it wasn't already */
5959 if (!info->pasid_enabled)
5960 iommu_enable_dev_iotlb(info);
5961
David Woodhouse2f26e0a2015-09-09 11:40:47 +01005962 ret = 0;
5963
5964 out:
5965 spin_unlock(&iommu->lock);
5966 spin_unlock_irqrestore(&device_domain_lock, flags);
5967
5968 return ret;
5969}
5970
James Sewart73bcbdc2019-05-25 13:41:23 +08005971static void intel_iommu_apply_resv_region(struct device *dev,
5972 struct iommu_domain *domain,
5973 struct iommu_resv_region *region)
5974{
5975 struct dmar_domain *dmar_domain = to_dmar_domain(domain);
5976 unsigned long start, end;
5977
5978 start = IOVA_PFN(region->start);
5979 end = IOVA_PFN(region->start + region->length - 1);
5980
5981 WARN_ON_ONCE(!reserve_iova(&dmar_domain->iovad, start, end));
5982}
5983
Patrick Steinhardt4a350a02019-12-27 00:56:18 +01005984static struct iommu_group *intel_iommu_device_group(struct device *dev)
5985{
5986 if (dev_is_pci(dev))
5987 return pci_device_group(dev);
5988 return generic_device_group(dev);
5989}
5990
Lu Baolud7cbc0f2019-03-25 09:30:29 +08005991#ifdef CONFIG_INTEL_IOMMU_SVM
David Woodhouse2f26e0a2015-09-09 11:40:47 +01005992struct intel_iommu *intel_svm_device_to_iommu(struct device *dev)
5993{
5994 struct intel_iommu *iommu;
5995 u8 bus, devfn;
5996
5997 if (iommu_dummy(dev)) {
5998 dev_warn(dev,
5999 "No IOMMU translation for device; cannot enable SVM\n");
6000 return NULL;
6001 }
6002
6003 iommu = device_to_iommu(dev, &bus, &devfn);
6004 if ((!iommu)) {
Sudeep Duttb9997e32015-10-18 20:54:37 -07006005 dev_err(dev, "No IOMMU for device; cannot enable SVM\n");
David Woodhouse2f26e0a2015-09-09 11:40:47 +01006006 return NULL;
6007 }
6008
David Woodhouse2f26e0a2015-09-09 11:40:47 +01006009 return iommu;
6010}
6011#endif /* CONFIG_INTEL_IOMMU_SVM */
6012
Lu Baolu95587a72019-03-25 09:30:30 +08006013static int intel_iommu_enable_auxd(struct device *dev)
6014{
6015 struct device_domain_info *info;
6016 struct intel_iommu *iommu;
6017 unsigned long flags;
6018 u8 bus, devfn;
6019 int ret;
6020
6021 iommu = device_to_iommu(dev, &bus, &devfn);
6022 if (!iommu || dmar_disabled)
6023 return -EINVAL;
6024
6025 if (!sm_supported(iommu) || !pasid_supported(iommu))
6026 return -EINVAL;
6027
6028 ret = intel_iommu_enable_pasid(iommu, dev);
6029 if (ret)
6030 return -ENODEV;
6031
6032 spin_lock_irqsave(&device_domain_lock, flags);
6033 info = dev->archdata.iommu;
6034 info->auxd_enabled = 1;
6035 spin_unlock_irqrestore(&device_domain_lock, flags);
6036
6037 return 0;
6038}
6039
6040static int intel_iommu_disable_auxd(struct device *dev)
6041{
6042 struct device_domain_info *info;
6043 unsigned long flags;
6044
6045 spin_lock_irqsave(&device_domain_lock, flags);
6046 info = dev->archdata.iommu;
6047 if (!WARN_ON(!info))
6048 info->auxd_enabled = 0;
6049 spin_unlock_irqrestore(&device_domain_lock, flags);
6050
6051 return 0;
6052}
6053
6054/*
6055 * A PCI express designated vendor specific extended capability is defined
6056 * in the section 3.7 of Intel scalable I/O virtualization technical spec
6057 * for system software and tools to detect endpoint devices supporting the
6058 * Intel scalable IO virtualization without host driver dependency.
6059 *
6060 * Returns the address of the matching extended capability structure within
6061 * the device's PCI configuration space or 0 if the device does not support
6062 * it.
6063 */
6064static int siov_find_pci_dvsec(struct pci_dev *pdev)
6065{
6066 int pos;
6067 u16 vendor, id;
6068
6069 pos = pci_find_next_ext_capability(pdev, 0, 0x23);
6070 while (pos) {
6071 pci_read_config_word(pdev, pos + 4, &vendor);
6072 pci_read_config_word(pdev, pos + 8, &id);
6073 if (vendor == PCI_VENDOR_ID_INTEL && id == 5)
6074 return pos;
6075
6076 pos = pci_find_next_ext_capability(pdev, pos, 0x23);
6077 }
6078
6079 return 0;
6080}
6081
6082static bool
6083intel_iommu_dev_has_feat(struct device *dev, enum iommu_dev_features feat)
6084{
6085 if (feat == IOMMU_DEV_FEAT_AUX) {
6086 int ret;
6087
6088 if (!dev_is_pci(dev) || dmar_disabled ||
6089 !scalable_mode_support() || !iommu_pasid_support())
6090 return false;
6091
6092 ret = pci_pasid_features(to_pci_dev(dev));
6093 if (ret < 0)
6094 return false;
6095
6096 return !!siov_find_pci_dvsec(to_pci_dev(dev));
6097 }
6098
6099 return false;
6100}
6101
6102static int
6103intel_iommu_dev_enable_feat(struct device *dev, enum iommu_dev_features feat)
6104{
6105 if (feat == IOMMU_DEV_FEAT_AUX)
6106 return intel_iommu_enable_auxd(dev);
6107
6108 return -ENODEV;
6109}
6110
6111static int
6112intel_iommu_dev_disable_feat(struct device *dev, enum iommu_dev_features feat)
6113{
6114 if (feat == IOMMU_DEV_FEAT_AUX)
6115 return intel_iommu_disable_auxd(dev);
6116
6117 return -ENODEV;
6118}
6119
6120static bool
6121intel_iommu_dev_feat_enabled(struct device *dev, enum iommu_dev_features feat)
6122{
6123 struct device_domain_info *info = dev->archdata.iommu;
6124
6125 if (feat == IOMMU_DEV_FEAT_AUX)
6126 return scalable_mode_support() && info && info->auxd_enabled;
6127
6128 return false;
6129}
6130
Lu Baolu0e8000f2019-03-25 09:30:33 +08006131static int
6132intel_iommu_aux_get_pasid(struct iommu_domain *domain, struct device *dev)
6133{
6134 struct dmar_domain *dmar_domain = to_dmar_domain(domain);
6135
6136 return dmar_domain->default_pasid > 0 ?
6137 dmar_domain->default_pasid : -EINVAL;
6138}
6139
Lu Baolu8af46c72019-05-25 13:41:32 +08006140static bool intel_iommu_is_attach_deferred(struct iommu_domain *domain,
6141 struct device *dev)
6142{
Joerg Roedel1d46159782020-02-17 17:12:37 +01006143 return attach_deferred(dev);
Lu Baolu8af46c72019-05-25 13:41:32 +08006144}
6145
Lu Baolu2cd13112020-01-02 08:18:15 +08006146static int
6147intel_iommu_domain_set_attr(struct iommu_domain *domain,
6148 enum iommu_attr attr, void *data)
6149{
6150 struct dmar_domain *dmar_domain = to_dmar_domain(domain);
6151 unsigned long flags;
6152 int ret = 0;
6153
6154 if (domain->type != IOMMU_DOMAIN_UNMANAGED)
6155 return -EINVAL;
6156
6157 switch (attr) {
6158 case DOMAIN_ATTR_NESTING:
6159 spin_lock_irqsave(&device_domain_lock, flags);
6160 if (nested_mode_support() &&
6161 list_empty(&dmar_domain->devices)) {
6162 dmar_domain->flags |= DOMAIN_FLAG_NESTING_MODE;
6163 dmar_domain->flags &= ~DOMAIN_FLAG_USE_FIRST_LEVEL;
6164 } else {
6165 ret = -ENODEV;
6166 }
6167 spin_unlock_irqrestore(&device_domain_lock, flags);
6168 break;
6169 default:
6170 ret = -EINVAL;
6171 break;
6172 }
6173
6174 return ret;
6175}
6176
Joerg Roedelb0119e82017-02-01 13:23:08 +01006177const struct iommu_ops intel_iommu_ops = {
Eric Auger0659b8d2017-01-19 20:57:53 +00006178 .capable = intel_iommu_capable,
6179 .domain_alloc = intel_iommu_domain_alloc,
6180 .domain_free = intel_iommu_domain_free,
Lu Baolu2cd13112020-01-02 08:18:15 +08006181 .domain_set_attr = intel_iommu_domain_set_attr,
Eric Auger0659b8d2017-01-19 20:57:53 +00006182 .attach_dev = intel_iommu_attach_device,
6183 .detach_dev = intel_iommu_detach_device,
Lu Baolu67b8e022019-03-25 09:30:32 +08006184 .aux_attach_dev = intel_iommu_aux_attach_device,
6185 .aux_detach_dev = intel_iommu_aux_detach_device,
Lu Baolu0e8000f2019-03-25 09:30:33 +08006186 .aux_get_pasid = intel_iommu_aux_get_pasid,
Eric Auger0659b8d2017-01-19 20:57:53 +00006187 .map = intel_iommu_map,
6188 .unmap = intel_iommu_unmap,
Eric Auger0659b8d2017-01-19 20:57:53 +00006189 .iova_to_phys = intel_iommu_iova_to_phys,
6190 .add_device = intel_iommu_add_device,
6191 .remove_device = intel_iommu_remove_device,
6192 .get_resv_regions = intel_iommu_get_resv_regions,
Thierry Reding0ecdebb2019-12-18 14:42:04 +01006193 .put_resv_regions = generic_iommu_put_resv_regions,
James Sewart73bcbdc2019-05-25 13:41:23 +08006194 .apply_resv_region = intel_iommu_apply_resv_region,
Patrick Steinhardt4a350a02019-12-27 00:56:18 +01006195 .device_group = intel_iommu_device_group,
Lu Baolu95587a72019-03-25 09:30:30 +08006196 .dev_has_feat = intel_iommu_dev_has_feat,
6197 .dev_feat_enabled = intel_iommu_dev_feat_enabled,
6198 .dev_enable_feat = intel_iommu_dev_enable_feat,
6199 .dev_disable_feat = intel_iommu_dev_disable_feat,
Lu Baolu8af46c72019-05-25 13:41:32 +08006200 .is_attach_deferred = intel_iommu_is_attach_deferred,
Eric Auger0659b8d2017-01-19 20:57:53 +00006201 .pgsize_bitmap = INTEL_IOMMU_PGSIZES,
Joerg Roedela8bcbb0d2008-12-03 15:14:02 +01006202};
David Woodhouse9af88142009-02-13 23:18:03 +00006203
Chris Wilson1f762492019-09-09 12:00:10 +01006204static void quirk_iommu_igfx(struct pci_dev *dev)
Daniel Vetter94526182013-01-20 23:50:13 +01006205{
Bjorn Helgaas932a6522019-02-08 16:06:00 -06006206 pci_info(dev, "Disabling IOMMU for graphics on this chipset\n");
Daniel Vetter94526182013-01-20 23:50:13 +01006207 dmar_map_gfx = 0;
6208}
6209
Chris Wilson1f762492019-09-09 12:00:10 +01006210/* G4x/GM45 integrated gfx dmar support is totally busted. */
6211DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2a40, quirk_iommu_igfx);
6212DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e00, quirk_iommu_igfx);
6213DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e10, quirk_iommu_igfx);
6214DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e20, quirk_iommu_igfx);
6215DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e30, quirk_iommu_igfx);
6216DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e40, quirk_iommu_igfx);
6217DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e90, quirk_iommu_igfx);
6218
6219/* Broadwell igfx malfunctions with dmar */
6220DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x1606, quirk_iommu_igfx);
6221DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x160B, quirk_iommu_igfx);
6222DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x160E, quirk_iommu_igfx);
6223DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x1602, quirk_iommu_igfx);
6224DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x160A, quirk_iommu_igfx);
6225DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x160D, quirk_iommu_igfx);
6226DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x1616, quirk_iommu_igfx);
6227DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x161B, quirk_iommu_igfx);
6228DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x161E, quirk_iommu_igfx);
6229DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x1612, quirk_iommu_igfx);
6230DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x161A, quirk_iommu_igfx);
6231DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x161D, quirk_iommu_igfx);
6232DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x1626, quirk_iommu_igfx);
6233DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x162B, quirk_iommu_igfx);
6234DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x162E, quirk_iommu_igfx);
6235DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x1622, quirk_iommu_igfx);
6236DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x162A, quirk_iommu_igfx);
6237DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x162D, quirk_iommu_igfx);
6238DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x1636, quirk_iommu_igfx);
6239DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x163B, quirk_iommu_igfx);
6240DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x163E, quirk_iommu_igfx);
6241DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x1632, quirk_iommu_igfx);
6242DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x163A, quirk_iommu_igfx);
6243DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x163D, quirk_iommu_igfx);
Daniel Vetter94526182013-01-20 23:50:13 +01006244
Greg Kroah-Hartmand34d6512012-12-21 15:05:21 -08006245static void quirk_iommu_rwbf(struct pci_dev *dev)
David Woodhouse9af88142009-02-13 23:18:03 +00006246{
6247 /*
6248 * Mobile 4 Series Chipset neglects to set RWBF capability,
Daniel Vetter210561f2013-01-21 19:48:59 +01006249 * but needs it. Same seems to hold for the desktop versions.
David Woodhouse9af88142009-02-13 23:18:03 +00006250 */
Bjorn Helgaas932a6522019-02-08 16:06:00 -06006251 pci_info(dev, "Forcing write-buffer flush capability\n");
David Woodhouse9af88142009-02-13 23:18:03 +00006252 rwbf_quirk = 1;
6253}
6254
6255DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2a40, quirk_iommu_rwbf);
Daniel Vetter210561f2013-01-21 19:48:59 +01006256DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e00, quirk_iommu_rwbf);
6257DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e10, quirk_iommu_rwbf);
6258DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e20, quirk_iommu_rwbf);
6259DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e30, quirk_iommu_rwbf);
6260DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e40, quirk_iommu_rwbf);
6261DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e90, quirk_iommu_rwbf);
David Woodhousee0fc7e02009-09-30 09:12:17 -07006262
Adam Jacksoneecfd572010-08-25 21:17:34 +01006263#define GGC 0x52
6264#define GGC_MEMORY_SIZE_MASK (0xf << 8)
6265#define GGC_MEMORY_SIZE_NONE (0x0 << 8)
6266#define GGC_MEMORY_SIZE_1M (0x1 << 8)
6267#define GGC_MEMORY_SIZE_2M (0x3 << 8)
6268#define GGC_MEMORY_VT_ENABLED (0x8 << 8)
6269#define GGC_MEMORY_SIZE_2M_VT (0x9 << 8)
6270#define GGC_MEMORY_SIZE_3M_VT (0xa << 8)
6271#define GGC_MEMORY_SIZE_4M_VT (0xb << 8)
6272
Greg Kroah-Hartmand34d6512012-12-21 15:05:21 -08006273static void quirk_calpella_no_shadow_gtt(struct pci_dev *dev)
David Woodhouse9eecabc2010-09-21 22:28:23 +01006274{
6275 unsigned short ggc;
6276
Adam Jacksoneecfd572010-08-25 21:17:34 +01006277 if (pci_read_config_word(dev, GGC, &ggc))
David Woodhouse9eecabc2010-09-21 22:28:23 +01006278 return;
6279
Adam Jacksoneecfd572010-08-25 21:17:34 +01006280 if (!(ggc & GGC_MEMORY_VT_ENABLED)) {
Bjorn Helgaas932a6522019-02-08 16:06:00 -06006281 pci_info(dev, "BIOS has allocated no shadow GTT; disabling IOMMU for graphics\n");
David Woodhouse9eecabc2010-09-21 22:28:23 +01006282 dmar_map_gfx = 0;
David Woodhouse6fbcfb32011-09-25 19:11:14 -07006283 } else if (dmar_map_gfx) {
6284 /* we have to ensure the gfx device is idle before we flush */
Bjorn Helgaas932a6522019-02-08 16:06:00 -06006285 pci_info(dev, "Disabling batched IOTLB flush on Ironlake\n");
David Woodhouse6fbcfb32011-09-25 19:11:14 -07006286 intel_iommu_strict = 1;
6287 }
David Woodhouse9eecabc2010-09-21 22:28:23 +01006288}
6289DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0040, quirk_calpella_no_shadow_gtt);
6290DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0044, quirk_calpella_no_shadow_gtt);
6291DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x0062, quirk_calpella_no_shadow_gtt);
6292DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x006a, quirk_calpella_no_shadow_gtt);
6293
David Woodhousee0fc7e02009-09-30 09:12:17 -07006294/* On Tylersburg chipsets, some BIOSes have been known to enable the
6295 ISOCH DMAR unit for the Azalia sound device, but not give it any
6296 TLB entries, which causes it to deadlock. Check for that. We do
6297 this in a function called from init_dmars(), instead of in a PCI
6298 quirk, because we don't want to print the obnoxious "BIOS broken"
6299 message if VT-d is actually disabled.
6300*/
6301static void __init check_tylersburg_isoch(void)
6302{
6303 struct pci_dev *pdev;
6304 uint32_t vtisochctrl;
6305
6306 /* If there's no Azalia in the system anyway, forget it. */
6307 pdev = pci_get_device(PCI_VENDOR_ID_INTEL, 0x3a3e, NULL);
6308 if (!pdev)
6309 return;
6310 pci_dev_put(pdev);
6311
6312 /* System Management Registers. Might be hidden, in which case
6313 we can't do the sanity check. But that's OK, because the
6314 known-broken BIOSes _don't_ actually hide it, so far. */
6315 pdev = pci_get_device(PCI_VENDOR_ID_INTEL, 0x342e, NULL);
6316 if (!pdev)
6317 return;
6318
6319 if (pci_read_config_dword(pdev, 0x188, &vtisochctrl)) {
6320 pci_dev_put(pdev);
6321 return;
6322 }
6323
6324 pci_dev_put(pdev);
6325
6326 /* If Azalia DMA is routed to the non-isoch DMAR unit, fine. */
6327 if (vtisochctrl & 1)
6328 return;
6329
6330 /* Drop all bits other than the number of TLB entries */
6331 vtisochctrl &= 0x1c;
6332
6333 /* If we have the recommended number of TLB entries (16), fine. */
6334 if (vtisochctrl == 0x10)
6335 return;
6336
6337 /* Zero TLB entries? You get to ride the short bus to school. */
6338 if (!vtisochctrl) {
6339 WARN(1, "Your BIOS is broken; DMA routed to ISOCH DMAR unit but no TLB space.\n"
6340 "BIOS vendor: %s; Ver: %s; Product Version: %s\n",
6341 dmi_get_system_info(DMI_BIOS_VENDOR),
6342 dmi_get_system_info(DMI_BIOS_VERSION),
6343 dmi_get_system_info(DMI_PRODUCT_VERSION));
6344 iommu_identity_mapping |= IDENTMAP_AZALIA;
6345 return;
6346 }
Joerg Roedel9f10e5b2015-06-12 09:57:06 +02006347
6348 pr_warn("Recommended TLB entries for ISOCH unit is 16; your BIOS set %d\n",
David Woodhousee0fc7e02009-09-30 09:12:17 -07006349 vtisochctrl);
6350}