Merge tag 'iommu-updates-v4.19' of git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu
Pull IOMMU updates from Joerg Roedel: - PASID table handling updates for the Intel VT-d driver. It implements a global PASID space now so that applications usings multiple devices will just have one PASID. - A new config option to make iommu passthroug mode the default. - New sysfs attribute for iommu groups to export the type of the default domain. - A debugfs interface (for debug only) usable by IOMMU drivers to export internals to user-space. - R-Car Gen3 SoCs support for the ipmmu-vmsa driver - The ARM-SMMU now aborts transactions from unknown devices and devices not attached to any domain. - Various cleanups and smaller fixes all over the place. * tag 'iommu-updates-v4.19' of git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu: (42 commits) iommu/omap: Fix cache flushes on L2 table entries iommu: Remove the ->map_sg indirection iommu/arm-smmu-v3: Abort all transactions if SMMU is enabled in kdump kernel iommu/arm-smmu-v3: Prevent any devices access to memory without registration iommu/ipmmu-vmsa: Don't register as BUS IOMMU if machine doesn't have IPMMU-VMSA iommu/ipmmu-vmsa: Clarify supported platforms iommu/ipmmu-vmsa: Fix allocation in atomic context iommu: Add config option to set passthrough as default iommu: Add sysfs attribyte for domain type iommu/arm-smmu-v3: sync the OVACKFLG to PRIQ consumer register iommu/arm-smmu: Error out only if not enough context interrupts iommu/io-pgtable-arm-v7s: Abort allocation when table address overflows the PTE iommu/io-pgtable-arm: Fix pgtable allocation in selftest iommu/vt-d: Remove the obsolete per iommu pasid tables iommu/vt-d: Apply per pci device pasid table in SVA iommu/vt-d: Allocate and free pasid table iommu/vt-d: Per PCI device pasid table interfaces iommu/vt-d: Add for_each_device_domain() helper iommu/vt-d: Move device_domain_info to header iommu/vt-d: Apply global PASID in SVA ...
This commit is contained in:
@@ -265,11 +265,6 @@ static inline void dmar_copy_shared_irte(struct irte *dst, struct irte *src)
|
||||
#define PDA_LOW_BIT 26
|
||||
#define PDA_HIGH_BIT 32
|
||||
|
||||
enum {
|
||||
IRQ_REMAP_XAPIC_MODE,
|
||||
IRQ_REMAP_X2APIC_MODE,
|
||||
};
|
||||
|
||||
/* Can't use the common MSI interrupt functions
|
||||
* since DMAR is not a pci device
|
||||
*/
|
||||
|
@@ -31,6 +31,7 @@
|
||||
#include <linux/list.h>
|
||||
#include <linux/iommu.h>
|
||||
#include <linux/io-64-nonatomic-lo-hi.h>
|
||||
#include <linux/dmar.h>
|
||||
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/iommu.h>
|
||||
@@ -114,6 +115,7 @@
|
||||
* Extended Capability Register
|
||||
*/
|
||||
|
||||
#define ecap_dit(e) ((e >> 41) & 0x1)
|
||||
#define ecap_pasid(e) ((e >> 40) & 0x1)
|
||||
#define ecap_pss(e) ((e >> 35) & 0x1f)
|
||||
#define ecap_eafs(e) ((e >> 34) & 0x1)
|
||||
@@ -284,6 +286,7 @@ enum {
|
||||
#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_PFSID(pfsid) (((u64)(pfsid & 0xf) << 12) | ((u64)(pfsid & 0xfff) << 52))
|
||||
#define QI_DEV_IOTLB_SIZE 1
|
||||
#define QI_DEV_IOTLB_MAX_INVS 32
|
||||
|
||||
@@ -308,6 +311,7 @@ enum {
|
||||
#define QI_DEV_EIOTLB_PASID(p) (((u64)p) << 32)
|
||||
#define QI_DEV_EIOTLB_SID(sid) ((u64)((sid) & 0xffff) << 16)
|
||||
#define QI_DEV_EIOTLB_QDEP(qd) ((u64)((qd) & 0x1f) << 4)
|
||||
#define QI_DEV_EIOTLB_PFSID(pfsid) (((u64)(pfsid & 0xf) << 12) | ((u64)(pfsid & 0xfff) << 52))
|
||||
#define QI_DEV_EIOTLB_MAX_INVS 32
|
||||
|
||||
#define QI_PGRP_IDX(idx) (((u64)(idx)) << 55)
|
||||
@@ -385,6 +389,42 @@ struct pasid_entry;
|
||||
struct pasid_state_entry;
|
||||
struct page_req_dsc;
|
||||
|
||||
struct dmar_domain {
|
||||
int nid; /* node id */
|
||||
|
||||
unsigned iommu_refcnt[DMAR_UNITS_SUPPORTED];
|
||||
/* Refcount of devices per iommu */
|
||||
|
||||
|
||||
u16 iommu_did[DMAR_UNITS_SUPPORTED];
|
||||
/* Domain ids per IOMMU. Use u16 since
|
||||
* domain ids are 16 bit wide according
|
||||
* to VT-d spec, section 9.3 */
|
||||
|
||||
bool has_iotlb_device;
|
||||
struct list_head devices; /* all devices' list */
|
||||
struct iova_domain iovad; /* iova's that belong to this domain */
|
||||
|
||||
struct dma_pte *pgd; /* virtual address */
|
||||
int gaw; /* max guest address width */
|
||||
|
||||
/* adjusted guest address width, 0 is level 2 30-bit */
|
||||
int agaw;
|
||||
|
||||
int flags; /* flags to find out type of domain */
|
||||
|
||||
int iommu_coherency;/* indicate coherency of iommu access */
|
||||
int iommu_snooping; /* indicate snooping control feature*/
|
||||
int iommu_count; /* reference count of iommu */
|
||||
int iommu_superpage;/* Level of superpages supported:
|
||||
0 == 4KiB (no superpages), 1 == 2MiB,
|
||||
2 == 1GiB, 3 == 512GiB, 4 == 1TiB */
|
||||
u64 max_addr; /* maximum mapped address */
|
||||
|
||||
struct iommu_domain domain; /* generic domain data structure for
|
||||
iommu core */
|
||||
};
|
||||
|
||||
struct intel_iommu {
|
||||
void __iomem *reg; /* Pointer to hardware regs, virtual addr */
|
||||
u64 reg_phys; /* physical address of hw register set */
|
||||
@@ -414,11 +454,9 @@ struct intel_iommu {
|
||||
* devices away to userspace processes (e.g. for DPDK) and don't
|
||||
* want to trust that userspace will use *only* the PASID it was
|
||||
* told to. But while it's all driver-arbitrated, we're fine. */
|
||||
struct pasid_entry *pasid_table;
|
||||
struct pasid_state_entry *pasid_state_table;
|
||||
struct page_req_dsc *prq;
|
||||
unsigned char prq_name[16]; /* Name for PRQ interrupt */
|
||||
struct idr pasid_idr;
|
||||
u32 pasid_max;
|
||||
#endif
|
||||
struct q_inval *qi; /* Queued invalidation info */
|
||||
@@ -434,6 +472,27 @@ struct intel_iommu {
|
||||
u32 flags; /* Software defined flags */
|
||||
};
|
||||
|
||||
/* PCI domain-device relationship */
|
||||
struct device_domain_info {
|
||||
struct list_head link; /* link to domain siblings */
|
||||
struct list_head global; /* link to global list */
|
||||
struct list_head table; /* link to pasid table */
|
||||
u8 bus; /* PCI bus number */
|
||||
u8 devfn; /* PCI devfn number */
|
||||
u16 pfsid; /* SRIOV physical function source ID */
|
||||
u8 pasid_supported:3;
|
||||
u8 pasid_enabled:1;
|
||||
u8 pri_supported:1;
|
||||
u8 pri_enabled:1;
|
||||
u8 ats_supported:1;
|
||||
u8 ats_enabled:1;
|
||||
u8 ats_qdep;
|
||||
struct device *dev; /* it's NULL for PCIe-to-PCI bridge */
|
||||
struct intel_iommu *iommu; /* IOMMU used by this device */
|
||||
struct dmar_domain *domain; /* pointer to domain */
|
||||
struct pasid_table *pasid_table; /* pasid table */
|
||||
};
|
||||
|
||||
static inline void __iommu_flush_cache(
|
||||
struct intel_iommu *iommu, void *addr, int size)
|
||||
{
|
||||
@@ -453,16 +512,22 @@ 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 void qi_flush_dev_iotlb(struct intel_iommu *iommu, u16 sid, u16 pfsid,
|
||||
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);
|
||||
|
||||
struct dmar_domain *get_valid_domain_for_dev(struct device *dev);
|
||||
void *alloc_pgtable_page(int node);
|
||||
void free_pgtable_page(void *vaddr);
|
||||
struct intel_iommu *domain_get_iommu(struct dmar_domain *domain);
|
||||
int for_each_device_domain(int (*fn)(struct device_domain_info *info,
|
||||
void *data), void *data);
|
||||
|
||||
#ifdef CONFIG_INTEL_IOMMU_SVM
|
||||
extern int intel_svm_alloc_pasid_tables(struct intel_iommu *iommu);
|
||||
extern int intel_svm_free_pasid_tables(struct intel_iommu *iommu);
|
||||
int intel_svm_init(struct intel_iommu *iommu);
|
||||
int intel_svm_exit(struct intel_iommu *iommu);
|
||||
extern int intel_svm_enable_prq(struct intel_iommu *iommu);
|
||||
extern int intel_svm_finish_prq(struct intel_iommu *iommu);
|
||||
|
||||
@@ -486,6 +551,7 @@ struct intel_svm {
|
||||
int flags;
|
||||
int pasid;
|
||||
struct list_head devs;
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
extern int intel_iommu_enable_pasid(struct intel_iommu *iommu, struct intel_svm_dev *sdev);
|
||||
|
@@ -166,8 +166,6 @@ struct iommu_resv_region {
|
||||
* @detach_dev: detach device from an iommu domain
|
||||
* @map: map a physically contiguous memory region to an iommu domain
|
||||
* @unmap: unmap a physically contiguous memory region from an iommu domain
|
||||
* @map_sg: map a scatter-gather list of physically contiguous memory chunks
|
||||
* to an iommu domain
|
||||
* @flush_tlb_all: Synchronously flush all hardware TLBs for this domain
|
||||
* @tlb_range_add: Add a given iova range to the flush queue for this domain
|
||||
* @tlb_sync: Flush all queued ranges from the hardware TLBs and empty flush
|
||||
@@ -201,8 +199,6 @@ struct iommu_ops {
|
||||
phys_addr_t paddr, size_t size, int prot);
|
||||
size_t (*unmap)(struct iommu_domain *domain, unsigned long iova,
|
||||
size_t size);
|
||||
size_t (*map_sg)(struct iommu_domain *domain, unsigned long iova,
|
||||
struct scatterlist *sg, unsigned int nents, int prot);
|
||||
void (*flush_iotlb_all)(struct iommu_domain *domain);
|
||||
void (*iotlb_range_add)(struct iommu_domain *domain,
|
||||
unsigned long iova, size_t size);
|
||||
@@ -303,9 +299,8 @@ extern size_t iommu_unmap(struct iommu_domain *domain, unsigned long iova,
|
||||
size_t size);
|
||||
extern size_t iommu_unmap_fast(struct iommu_domain *domain,
|
||||
unsigned long iova, size_t size);
|
||||
extern size_t default_iommu_map_sg(struct iommu_domain *domain, unsigned long iova,
|
||||
struct scatterlist *sg,unsigned int nents,
|
||||
int prot);
|
||||
extern size_t iommu_map_sg(struct iommu_domain *domain, unsigned long iova,
|
||||
struct scatterlist *sg,unsigned int nents, int prot);
|
||||
extern phys_addr_t iommu_iova_to_phys(struct iommu_domain *domain, dma_addr_t iova);
|
||||
extern void iommu_set_fault_handler(struct iommu_domain *domain,
|
||||
iommu_fault_handler_t handler, void *token);
|
||||
@@ -378,13 +373,6 @@ static inline void iommu_tlb_sync(struct iommu_domain *domain)
|
||||
domain->ops->iotlb_sync(domain);
|
||||
}
|
||||
|
||||
static inline size_t iommu_map_sg(struct iommu_domain *domain,
|
||||
unsigned long iova, struct scatterlist *sg,
|
||||
unsigned int nents, int prot)
|
||||
{
|
||||
return domain->ops->map_sg(domain, iova, sg, nents, prot);
|
||||
}
|
||||
|
||||
/* PCI device grouping function */
|
||||
extern struct iommu_group *pci_device_group(struct device *dev);
|
||||
/* Generic device grouping function */
|
||||
@@ -698,4 +686,11 @@ const struct iommu_ops *iommu_ops_from_fwnode(struct fwnode_handle *fwnode)
|
||||
|
||||
#endif /* CONFIG_IOMMU_API */
|
||||
|
||||
#ifdef CONFIG_IOMMU_DEBUGFS
|
||||
extern struct dentry *iommu_debugfs_dir;
|
||||
void iommu_debugfs_setup(void);
|
||||
#else
|
||||
static inline void iommu_debugfs_setup(void) {}
|
||||
#endif
|
||||
|
||||
#endif /* __LINUX_IOMMU_H */
|
||||
|
@@ -1,18 +0,0 @@
|
||||
/* sh_ipmmu.h
|
||||
*
|
||||
* Copyright (C) 2012 Hideki EIRAKU
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*/
|
||||
|
||||
#ifndef __SH_IPMMU_H__
|
||||
#define __SH_IPMMU_H__
|
||||
|
||||
struct shmobile_ipmmu_platform_data {
|
||||
const char * const *dev_names;
|
||||
unsigned int num_dev_names;
|
||||
};
|
||||
|
||||
#endif /* __SH_IPMMU_H__ */
|
Reference in New Issue
Block a user