6eae81a5e2
This time with bigger changes than usual: * A new IOMMU driver for the ARM SMMUv3. This IOMMU is pretty different from SMMUv1 and v2 in that it is configured through in-memory structures and not through the MMIO register region. The ARM SMMUv3 also supports IO demand paging for PCI devices with PRI/PASID capabilities, but this is not implemented in the driver yet. * Lots of cleanups and device-tree support for the Exynos IOMMU driver. This is part of the effort to bring Exynos DRM support upstream. * Introduction of default domains into the IOMMU core code. The rationale behind this is to move functionalily out of the IOMMU drivers to common code to get to a unified behavior between different drivers. The patches here introduce a default domain for iommu-groups (isolation groups). A device will now always be attached to a domain, either the default domain or another domain handled by the device driver. The IOMMU drivers have to be modified to make use of that feature. So long the AMD IOMMU driver is converted, with others to follow. * Patches for the Intel VT-d drvier to fix DMAR faults that happen when a kdump kernel boots. When the kdump kernel boots it re-initializes the IOMMU hardware, which destroys all mappings from the crashed kernel. As this happens before the endpoint devices are re-initialized, any in-flight DMA causes a DMAR fault. These faults cause PCI master aborts, which some devices can't handle properly and go into an undefined state, so that the device driver in the kdump kernel fails to initialize them and the dump fails. This is now fixed by copying over the mapping structures (only context tables and interrupt remapping tables) from the old kernel and keep the old mappings in place until the device driver of the new kernel takes over. This emulates the the behavior without an IOMMU to the best degree possible. * A couple of other small fixes and cleanups. -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.22 (GNU/Linux) iQIcBAABAgAGBQJViSIWAAoJECvwRC2XARrjl+cP/2FXS7SWDq91VFiIZfXfPt8H C5Ef3OGWCnMzn4MKE1ExkyDhC+AH6pF1s4zi3XfT6b8iOA+DUpa51rxJjixszt31 tQwmvB7hWu4mznGxSN7EA0Pm0l/v3tBAY5BvG598af0aNZFFJ6po+31MyQA5X67+ 6xpqLbH/hm4IZhFBOEzZwxuWWsNxlJwwzKqeAjGyqeUhdruRYZiPHWQ17sDjwLM/ QcVvWBb7meOtKv1OCtpzC4sglSk3scbAfEHMEBuDt8cI6OD7/t2VzPXDWWZuXGqK nRAxCT7NrXvyOnv0xwdn0j5p1FUGipVxvhsGWX7sJsh3UHWm8Q+5rRKFFVI9pm50 QcMjiIMazK5VwcAkDnLoDgSz4Zz6TfHXEOqSJ2vjTPt2VDP/J9zdM2iwHx2ujicI mIkrtmsBprvAPx6e9jcqiS5L/Xy1y1xewXuGxa5F2XOjqdoXkPqaupjlyrWzrChA MC8w67FdzjHDPCfIqfIWZpJQj4f1OFQGd3HS5HpkBACxIwCg85gRw4DEMfD/sirO BL2VM0RO/bB5+4R0AY7UA2VszQvNMqedj1bA4vAbrnXqOh8BI/0GgeoWiBMXhyX1 qvT1jl+cxuCm5tgBOMUGYoRyF+//bH+l78jLsTYaWRtuVzFlkAX6idNvYYK0dmNt tLII2IIZBk87P3pF4d6A =Zicw -----END PGP SIGNATURE----- Merge tag 'iommu-updates-v4.2' of git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu Pull IOMMU updates from Joerg Roedel: "This time with bigger changes than usual: - A new IOMMU driver for the ARM SMMUv3. This IOMMU is pretty different from SMMUv1 and v2 in that it is configured through in-memory structures and not through the MMIO register region. The ARM SMMUv3 also supports IO demand paging for PCI devices with PRI/PASID capabilities, but this is not implemented in the driver yet. - Lots of cleanups and device-tree support for the Exynos IOMMU driver. This is part of the effort to bring Exynos DRM support upstream. - Introduction of default domains into the IOMMU core code. The rationale behind this is to move functionalily out of the IOMMU drivers to common code to get to a unified behavior between different drivers. The patches here introduce a default domain for iommu-groups (isolation groups). A device will now always be attached to a domain, either the default domain or another domain handled by the device driver. The IOMMU drivers have to be modified to make use of that feature. So long the AMD IOMMU driver is converted, with others to follow. - Patches for the Intel VT-d drvier to fix DMAR faults that happen when a kdump kernel boots. When the kdump kernel boots it re-initializes the IOMMU hardware, which destroys all mappings from the crashed kernel. As this happens before the endpoint devices are re-initialized, any in-flight DMA causes a DMAR fault. These faults cause PCI master aborts, which some devices can't handle properly and go into an undefined state, so that the device driver in the kdump kernel fails to initialize them and the dump fails. This is now fixed by copying over the mapping structures (only context tables and interrupt remapping tables) from the old kernel and keep the old mappings in place until the device driver of the new kernel takes over. This emulates the the behavior without an IOMMU to the best degree possible. - A couple of other small fixes and cleanups" * tag 'iommu-updates-v4.2' of git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu: (69 commits) iommu/amd: Handle large pages correctly in free_pagetable iommu/vt-d: Don't disable IR when it was previously enabled iommu/vt-d: Make sure copied over IR entries are not reused iommu/vt-d: Copy IR table from old kernel when in kdump mode iommu/vt-d: Set IRTA in intel_setup_irq_remapping iommu/vt-d: Disable IRQ remapping in intel_prepare_irq_remapping iommu/vt-d: Move QI initializationt to intel_setup_irq_remapping iommu/vt-d: Move EIM detection to intel_prepare_irq_remapping iommu/vt-d: Enable Translation only if it was previously disabled iommu/vt-d: Don't disable translation prior to OS handover iommu/vt-d: Don't copy translation tables if RTT bit needs to be changed iommu/vt-d: Don't do early domain assignment if kdump kernel iommu/vt-d: Allocate si_domain in init_dmars() iommu/vt-d: Mark copied context entries iommu/vt-d: Do not re-use domain-ids from the old kernel iommu/vt-d: Copy translation tables from old kernel iommu/vt-d: Detect pre enabled translation iommu/vt-d: Make root entry visible for hardware right after allocation iommu/vt-d: Init QI before root entry is allocated iommu/vt-d: Cleanup log messages ...
394 lines
13 KiB
C
394 lines
13 KiB
C
/*
|
|
* Copyright (c) 2006, Intel Corporation.
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
* under the terms and conditions of the GNU General Public License,
|
|
* version 2, as published by the Free Software Foundation.
|
|
*
|
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
* more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along with
|
|
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
|
* Place - Suite 330, Boston, MA 02111-1307 USA.
|
|
*
|
|
* Copyright (C) 2006-2008 Intel Corporation
|
|
* Author: Ashok Raj <ashok.raj@intel.com>
|
|
* Author: Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
|
|
*/
|
|
|
|
#ifndef _INTEL_IOMMU_H_
|
|
#define _INTEL_IOMMU_H_
|
|
|
|
#include <linux/types.h>
|
|
#include <linux/iova.h>
|
|
#include <linux/io.h>
|
|
#include <linux/dma_remapping.h>
|
|
#include <asm/cacheflush.h>
|
|
#include <asm/iommu.h>
|
|
|
|
/*
|
|
* Intel IOMMU register specification per version 1.0 public spec.
|
|
*/
|
|
|
|
#define DMAR_VER_REG 0x0 /* Arch version supported by this IOMMU */
|
|
#define DMAR_CAP_REG 0x8 /* Hardware supported capabilities */
|
|
#define DMAR_ECAP_REG 0x10 /* Extended capabilities supported */
|
|
#define DMAR_GCMD_REG 0x18 /* Global command register */
|
|
#define DMAR_GSTS_REG 0x1c /* Global status register */
|
|
#define DMAR_RTADDR_REG 0x20 /* Root entry table */
|
|
#define DMAR_CCMD_REG 0x28 /* Context command reg */
|
|
#define DMAR_FSTS_REG 0x34 /* Fault Status register */
|
|
#define DMAR_FECTL_REG 0x38 /* Fault control register */
|
|
#define DMAR_FEDATA_REG 0x3c /* Fault event interrupt data register */
|
|
#define DMAR_FEADDR_REG 0x40 /* Fault event interrupt addr register */
|
|
#define DMAR_FEUADDR_REG 0x44 /* Upper address register */
|
|
#define DMAR_AFLOG_REG 0x58 /* Advanced Fault control */
|
|
#define DMAR_PMEN_REG 0x64 /* Enable Protected Memory Region */
|
|
#define DMAR_PLMBASE_REG 0x68 /* PMRR Low addr */
|
|
#define DMAR_PLMLIMIT_REG 0x6c /* PMRR low limit */
|
|
#define DMAR_PHMBASE_REG 0x70 /* pmrr high base addr */
|
|
#define DMAR_PHMLIMIT_REG 0x78 /* pmrr high limit */
|
|
#define DMAR_IQH_REG 0x80 /* Invalidation queue head register */
|
|
#define DMAR_IQT_REG 0x88 /* Invalidation queue tail register */
|
|
#define DMAR_IQ_SHIFT 4 /* Invalidation queue head/tail shift */
|
|
#define DMAR_IQA_REG 0x90 /* Invalidation queue addr register */
|
|
#define DMAR_ICS_REG 0x9c /* Invalidation complete status register */
|
|
#define DMAR_IRTA_REG 0xb8 /* Interrupt remapping table addr register */
|
|
|
|
#define OFFSET_STRIDE (9)
|
|
/*
|
|
#define dmar_readl(dmar, reg) readl(dmar + reg)
|
|
#define dmar_readq(dmar, reg) ({ \
|
|
u32 lo, hi; \
|
|
lo = readl(dmar + reg); \
|
|
hi = readl(dmar + reg + 4); \
|
|
(((u64) hi) << 32) + lo; })
|
|
*/
|
|
static inline u64 dmar_readq(void __iomem *addr)
|
|
{
|
|
u32 lo, hi;
|
|
lo = readl(addr);
|
|
hi = readl(addr + 4);
|
|
return (((u64) hi) << 32) + lo;
|
|
}
|
|
|
|
static inline void dmar_writeq(void __iomem *addr, u64 val)
|
|
{
|
|
writel((u32)val, addr);
|
|
writel((u32)(val >> 32), addr + 4);
|
|
}
|
|
|
|
#define DMAR_VER_MAJOR(v) (((v) & 0xf0) >> 4)
|
|
#define DMAR_VER_MINOR(v) ((v) & 0x0f)
|
|
|
|
/*
|
|
* Decoding Capability Register
|
|
*/
|
|
#define cap_pi_support(c) (((c) >> 59) & 1)
|
|
#define cap_read_drain(c) (((c) >> 55) & 1)
|
|
#define cap_write_drain(c) (((c) >> 54) & 1)
|
|
#define cap_max_amask_val(c) (((c) >> 48) & 0x3f)
|
|
#define cap_num_fault_regs(c) ((((c) >> 40) & 0xff) + 1)
|
|
#define cap_pgsel_inv(c) (((c) >> 39) & 1)
|
|
|
|
#define cap_super_page_val(c) (((c) >> 34) & 0xf)
|
|
#define cap_super_offset(c) (((find_first_bit(&cap_super_page_val(c), 4)) \
|
|
* OFFSET_STRIDE) + 21)
|
|
|
|
#define cap_fault_reg_offset(c) ((((c) >> 24) & 0x3ff) * 16)
|
|
#define cap_max_fault_reg_offset(c) \
|
|
(cap_fault_reg_offset(c) + cap_num_fault_regs(c) * 16)
|
|
|
|
#define cap_zlr(c) (((c) >> 22) & 1)
|
|
#define cap_isoch(c) (((c) >> 23) & 1)
|
|
#define cap_mgaw(c) ((((c) >> 16) & 0x3f) + 1)
|
|
#define cap_sagaw(c) (((c) >> 8) & 0x1f)
|
|
#define cap_caching_mode(c) (((c) >> 7) & 1)
|
|
#define cap_phmr(c) (((c) >> 6) & 1)
|
|
#define cap_plmr(c) (((c) >> 5) & 1)
|
|
#define cap_rwbf(c) (((c) >> 4) & 1)
|
|
#define cap_afl(c) (((c) >> 3) & 1)
|
|
#define cap_ndoms(c) (((unsigned long)1) << (4 + 2 * ((c) & 0x7)))
|
|
/*
|
|
* Extended Capability Register
|
|
*/
|
|
|
|
#define ecap_pasid(e) ((e >> 40) & 0x1)
|
|
#define ecap_pss(e) ((e >> 35) & 0x1f)
|
|
#define ecap_eafs(e) ((e >> 34) & 0x1)
|
|
#define ecap_nwfs(e) ((e >> 33) & 0x1)
|
|
#define ecap_srs(e) ((e >> 31) & 0x1)
|
|
#define ecap_ers(e) ((e >> 30) & 0x1)
|
|
#define ecap_prs(e) ((e >> 29) & 0x1)
|
|
/* PASID support used to be on bit 28 */
|
|
#define ecap_dis(e) ((e >> 27) & 0x1)
|
|
#define ecap_nest(e) ((e >> 26) & 0x1)
|
|
#define ecap_mts(e) ((e >> 25) & 0x1)
|
|
#define ecap_ecs(e) ((e >> 24) & 0x1)
|
|
#define ecap_iotlb_offset(e) ((((e) >> 8) & 0x3ff) * 16)
|
|
#define ecap_max_iotlb_offset(e) (ecap_iotlb_offset(e) + 16)
|
|
#define ecap_coherent(e) ((e) & 0x1)
|
|
#define ecap_qis(e) ((e) & 0x2)
|
|
#define ecap_pass_through(e) ((e >> 6) & 0x1)
|
|
#define ecap_eim_support(e) ((e >> 4) & 0x1)
|
|
#define ecap_ir_support(e) ((e >> 3) & 0x1)
|
|
#define ecap_dev_iotlb_support(e) (((e) >> 2) & 0x1)
|
|
#define ecap_max_handle_mask(e) ((e >> 20) & 0xf)
|
|
#define ecap_sc_support(e) ((e >> 7) & 0x1) /* Snooping Control */
|
|
|
|
/* IOTLB_REG */
|
|
#define DMA_TLB_FLUSH_GRANU_OFFSET 60
|
|
#define DMA_TLB_GLOBAL_FLUSH (((u64)1) << 60)
|
|
#define DMA_TLB_DSI_FLUSH (((u64)2) << 60)
|
|
#define DMA_TLB_PSI_FLUSH (((u64)3) << 60)
|
|
#define DMA_TLB_IIRG(type) ((type >> 60) & 7)
|
|
#define DMA_TLB_IAIG(val) (((val) >> 57) & 7)
|
|
#define DMA_TLB_READ_DRAIN (((u64)1) << 49)
|
|
#define DMA_TLB_WRITE_DRAIN (((u64)1) << 48)
|
|
#define DMA_TLB_DID(id) (((u64)((id) & 0xffff)) << 32)
|
|
#define DMA_TLB_IVT (((u64)1) << 63)
|
|
#define DMA_TLB_IH_NONLEAF (((u64)1) << 6)
|
|
#define DMA_TLB_MAX_SIZE (0x3f)
|
|
|
|
/* INVALID_DESC */
|
|
#define DMA_CCMD_INVL_GRANU_OFFSET 61
|
|
#define DMA_ID_TLB_GLOBAL_FLUSH (((u64)1) << 3)
|
|
#define DMA_ID_TLB_DSI_FLUSH (((u64)2) << 3)
|
|
#define DMA_ID_TLB_PSI_FLUSH (((u64)3) << 3)
|
|
#define DMA_ID_TLB_READ_DRAIN (((u64)1) << 7)
|
|
#define DMA_ID_TLB_WRITE_DRAIN (((u64)1) << 6)
|
|
#define DMA_ID_TLB_DID(id) (((u64)((id & 0xffff) << 16)))
|
|
#define DMA_ID_TLB_IH_NONLEAF (((u64)1) << 6)
|
|
#define DMA_ID_TLB_ADDR(addr) (addr)
|
|
#define DMA_ID_TLB_ADDR_MASK(mask) (mask)
|
|
|
|
/* PMEN_REG */
|
|
#define DMA_PMEN_EPM (((u32)1)<<31)
|
|
#define DMA_PMEN_PRS (((u32)1)<<0)
|
|
|
|
/* GCMD_REG */
|
|
#define DMA_GCMD_TE (((u32)1) << 31)
|
|
#define DMA_GCMD_SRTP (((u32)1) << 30)
|
|
#define DMA_GCMD_SFL (((u32)1) << 29)
|
|
#define DMA_GCMD_EAFL (((u32)1) << 28)
|
|
#define DMA_GCMD_WBF (((u32)1) << 27)
|
|
#define DMA_GCMD_QIE (((u32)1) << 26)
|
|
#define DMA_GCMD_SIRTP (((u32)1) << 24)
|
|
#define DMA_GCMD_IRE (((u32) 1) << 25)
|
|
#define DMA_GCMD_CFI (((u32) 1) << 23)
|
|
|
|
/* GSTS_REG */
|
|
#define DMA_GSTS_TES (((u32)1) << 31)
|
|
#define DMA_GSTS_RTPS (((u32)1) << 30)
|
|
#define DMA_GSTS_FLS (((u32)1) << 29)
|
|
#define DMA_GSTS_AFLS (((u32)1) << 28)
|
|
#define DMA_GSTS_WBFS (((u32)1) << 27)
|
|
#define DMA_GSTS_QIES (((u32)1) << 26)
|
|
#define DMA_GSTS_IRTPS (((u32)1) << 24)
|
|
#define DMA_GSTS_IRES (((u32)1) << 25)
|
|
#define DMA_GSTS_CFIS (((u32)1) << 23)
|
|
|
|
/* DMA_RTADDR_REG */
|
|
#define DMA_RTADDR_RTT (((u64)1) << 11)
|
|
|
|
/* CCMD_REG */
|
|
#define DMA_CCMD_ICC (((u64)1) << 63)
|
|
#define DMA_CCMD_GLOBAL_INVL (((u64)1) << 61)
|
|
#define DMA_CCMD_DOMAIN_INVL (((u64)2) << 61)
|
|
#define DMA_CCMD_DEVICE_INVL (((u64)3) << 61)
|
|
#define DMA_CCMD_FM(m) (((u64)((m) & 0x3)) << 32)
|
|
#define DMA_CCMD_MASK_NOBIT 0
|
|
#define DMA_CCMD_MASK_1BIT 1
|
|
#define DMA_CCMD_MASK_2BIT 2
|
|
#define DMA_CCMD_MASK_3BIT 3
|
|
#define DMA_CCMD_SID(s) (((u64)((s) & 0xffff)) << 16)
|
|
#define DMA_CCMD_DID(d) ((u64)((d) & 0xffff))
|
|
|
|
/* FECTL_REG */
|
|
#define DMA_FECTL_IM (((u32)1) << 31)
|
|
|
|
/* FSTS_REG */
|
|
#define DMA_FSTS_PPF ((u32)2)
|
|
#define DMA_FSTS_PFO ((u32)1)
|
|
#define DMA_FSTS_IQE (1 << 4)
|
|
#define DMA_FSTS_ICE (1 << 5)
|
|
#define DMA_FSTS_ITE (1 << 6)
|
|
#define dma_fsts_fault_record_index(s) (((s) >> 8) & 0xff)
|
|
|
|
/* FRCD_REG, 32 bits access */
|
|
#define DMA_FRCD_F (((u32)1) << 31)
|
|
#define dma_frcd_type(d) ((d >> 30) & 1)
|
|
#define dma_frcd_fault_reason(c) (c & 0xff)
|
|
#define dma_frcd_source_id(c) (c & 0xffff)
|
|
/* low 64 bit */
|
|
#define dma_frcd_page_addr(d) (d & (((u64)-1) << PAGE_SHIFT))
|
|
|
|
#define IOMMU_WAIT_OP(iommu, offset, op, cond, sts) \
|
|
do { \
|
|
cycles_t start_time = get_cycles(); \
|
|
while (1) { \
|
|
sts = op(iommu->reg + offset); \
|
|
if (cond) \
|
|
break; \
|
|
if (DMAR_OPERATION_TIMEOUT < (get_cycles() - start_time))\
|
|
panic("DMAR hardware is malfunctioning\n"); \
|
|
cpu_relax(); \
|
|
} \
|
|
} while (0)
|
|
|
|
#define QI_LENGTH 256 /* queue length */
|
|
|
|
enum {
|
|
QI_FREE,
|
|
QI_IN_USE,
|
|
QI_DONE,
|
|
QI_ABORT
|
|
};
|
|
|
|
#define QI_CC_TYPE 0x1
|
|
#define QI_IOTLB_TYPE 0x2
|
|
#define QI_DIOTLB_TYPE 0x3
|
|
#define QI_IEC_TYPE 0x4
|
|
#define QI_IWD_TYPE 0x5
|
|
|
|
#define QI_IEC_SELECTIVE (((u64)1) << 4)
|
|
#define QI_IEC_IIDEX(idx) (((u64)(idx & 0xffff) << 32))
|
|
#define QI_IEC_IM(m) (((u64)(m & 0x1f) << 27))
|
|
|
|
#define QI_IWD_STATUS_DATA(d) (((u64)d) << 32)
|
|
#define QI_IWD_STATUS_WRITE (((u64)1) << 5)
|
|
|
|
#define QI_IOTLB_DID(did) (((u64)did) << 16)
|
|
#define QI_IOTLB_DR(dr) (((u64)dr) << 7)
|
|
#define QI_IOTLB_DW(dw) (((u64)dw) << 6)
|
|
#define QI_IOTLB_GRAN(gran) (((u64)gran) >> (DMA_TLB_FLUSH_GRANU_OFFSET-4))
|
|
#define QI_IOTLB_ADDR(addr) (((u64)addr) & VTD_PAGE_MASK)
|
|
#define QI_IOTLB_IH(ih) (((u64)ih) << 6)
|
|
#define QI_IOTLB_AM(am) (((u8)am))
|
|
|
|
#define QI_CC_FM(fm) (((u64)fm) << 48)
|
|
#define QI_CC_SID(sid) (((u64)sid) << 32)
|
|
#define QI_CC_DID(did) (((u64)did) << 16)
|
|
#define QI_CC_GRAN(gran) (((u64)gran) >> (DMA_CCMD_INVL_GRANU_OFFSET-4))
|
|
|
|
#define QI_DEV_IOTLB_SID(sid) ((u64)((sid) & 0xffff) << 32)
|
|
#define QI_DEV_IOTLB_QDEP(qdep) (((qdep) & 0x1f) << 16)
|
|
#define QI_DEV_IOTLB_ADDR(addr) ((u64)(addr) & VTD_PAGE_MASK)
|
|
#define QI_DEV_IOTLB_SIZE 1
|
|
#define QI_DEV_IOTLB_MAX_INVS 32
|
|
|
|
struct qi_desc {
|
|
u64 low, high;
|
|
};
|
|
|
|
struct q_inval {
|
|
raw_spinlock_t q_lock;
|
|
struct qi_desc *desc; /* invalidation queue */
|
|
int *desc_status; /* desc status */
|
|
int free_head; /* first free entry */
|
|
int free_tail; /* last free entry */
|
|
int free_cnt;
|
|
};
|
|
|
|
#ifdef CONFIG_IRQ_REMAP
|
|
/* 1MB - maximum possible interrupt remapping table size */
|
|
#define INTR_REMAP_PAGE_ORDER 8
|
|
#define INTR_REMAP_TABLE_REG_SIZE 0xf
|
|
#define INTR_REMAP_TABLE_REG_SIZE_MASK 0xf
|
|
|
|
#define INTR_REMAP_TABLE_ENTRIES 65536
|
|
|
|
struct irq_domain;
|
|
|
|
struct ir_table {
|
|
struct irte *base;
|
|
unsigned long *bitmap;
|
|
};
|
|
#endif
|
|
|
|
struct iommu_flush {
|
|
void (*flush_context)(struct intel_iommu *iommu, u16 did, u16 sid,
|
|
u8 fm, u64 type);
|
|
void (*flush_iotlb)(struct intel_iommu *iommu, u16 did, u64 addr,
|
|
unsigned int size_order, u64 type);
|
|
};
|
|
|
|
enum {
|
|
SR_DMAR_FECTL_REG,
|
|
SR_DMAR_FEDATA_REG,
|
|
SR_DMAR_FEADDR_REG,
|
|
SR_DMAR_FEUADDR_REG,
|
|
MAX_SR_DMAR_REGS
|
|
};
|
|
|
|
#define VTD_FLAG_TRANS_PRE_ENABLED (1 << 0)
|
|
#define VTD_FLAG_IRQ_REMAP_PRE_ENABLED (1 << 1)
|
|
|
|
struct intel_iommu {
|
|
void __iomem *reg; /* Pointer to hardware regs, virtual addr */
|
|
u64 reg_phys; /* physical address of hw register set */
|
|
u64 reg_size; /* size of hw register set */
|
|
u64 cap;
|
|
u64 ecap;
|
|
u32 gcmd; /* Holds TE, EAFL. Don't need SRTP, SFL, WBF */
|
|
raw_spinlock_t register_lock; /* protect register handling */
|
|
int seq_id; /* sequence id of the iommu */
|
|
int agaw; /* agaw of this iommu */
|
|
int msagaw; /* max sagaw of this iommu */
|
|
unsigned int irq;
|
|
u16 segment; /* PCI segment# */
|
|
unsigned char name[13]; /* Device Name */
|
|
|
|
#ifdef CONFIG_INTEL_IOMMU
|
|
unsigned long *domain_ids; /* bitmap of domains */
|
|
struct dmar_domain **domains; /* ptr to domains */
|
|
spinlock_t lock; /* protect context, domain ids */
|
|
struct root_entry *root_entry; /* virtual address */
|
|
|
|
struct iommu_flush flush;
|
|
#endif
|
|
struct q_inval *qi; /* Queued invalidation info */
|
|
u32 *iommu_state; /* Store iommu states between suspend and resume.*/
|
|
|
|
#ifdef CONFIG_IRQ_REMAP
|
|
struct ir_table *ir_table; /* Interrupt remapping info */
|
|
struct irq_domain *ir_domain;
|
|
struct irq_domain *ir_msi_domain;
|
|
#endif
|
|
struct device *iommu_dev; /* IOMMU-sysfs device */
|
|
int node;
|
|
u32 flags; /* Software defined flags */
|
|
};
|
|
|
|
static inline void __iommu_flush_cache(
|
|
struct intel_iommu *iommu, void *addr, int size)
|
|
{
|
|
if (!ecap_coherent(iommu->ecap))
|
|
clflush_cache_range(addr, size);
|
|
}
|
|
|
|
extern struct dmar_drhd_unit * dmar_find_matched_drhd_unit(struct pci_dev *dev);
|
|
extern int dmar_find_matched_atsr_unit(struct pci_dev *dev);
|
|
|
|
extern int dmar_enable_qi(struct intel_iommu *iommu);
|
|
extern void dmar_disable_qi(struct intel_iommu *iommu);
|
|
extern int dmar_reenable_qi(struct intel_iommu *iommu);
|
|
extern void qi_global_iec(struct intel_iommu *iommu);
|
|
|
|
extern void qi_flush_context(struct intel_iommu *iommu, u16 did, u16 sid,
|
|
u8 fm, u64 type);
|
|
extern void qi_flush_iotlb(struct intel_iommu *iommu, u16 did, u64 addr,
|
|
unsigned int size_order, u64 type);
|
|
extern void qi_flush_dev_iotlb(struct intel_iommu *iommu, u16 sid, u16 qdep,
|
|
u64 addr, unsigned mask);
|
|
|
|
extern int qi_submit_sync(struct qi_desc *desc, struct intel_iommu *iommu);
|
|
|
|
extern int dmar_ir_support(void);
|
|
|
|
extern const struct attribute_group *intel_iommu_groups[];
|
|
|
|
#endif
|