Commit 6855d1ba authored by Joerg Roedel's avatar Joerg Roedel

Merge tag 'arm-smmu-updates' of...

Merge tag 'arm-smmu-updates' of git://git.kernel.org/pub/scm/linux/kernel/git/will/linux into arm/smmu

Arm SMMU updates for 5.6

- Support for building, and {un,}loading the SMMU drivers as modules

- Minor cleanups

- SMMUv3:
  * Non-critical fix to encoding of TLBI_NH_VA invalidation command
  * Fix broken sanity check on size of MMIO resource during probe
  * Support for Substream IDs which will soon be provided by PCI PASIDs

- io-pgtable:
  * Finish off the TTBR1 preparation work partially merged last cycle
  * Ensure correct memory attributes for non-cacheable mappings

- SMMU:
  * Namespace public #defines to avoid collisions with arch/arm64/
  * Avoid using valid SMR register when probing mask size
parents 1ea27ee2 5a4549fd
...@@ -86,6 +86,12 @@ have a means to turn off translation. But it is invalid in such cases to ...@@ -86,6 +86,12 @@ have a means to turn off translation. But it is invalid in such cases to
disable the IOMMU's device tree node in the first place because it would disable the IOMMU's device tree node in the first place because it would
prevent any driver from properly setting up the translations. prevent any driver from properly setting up the translations.
Optional properties:
--------------------
- pasid-num-bits: Some masters support multiple address spaces for DMA, by
tagging DMA transactions with an address space identifier. By default,
this is 0, which means that the device only has one address space.
Notes: Notes:
====== ======
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#define pr_fmt(fmt) "ACPI: IORT: " fmt #define pr_fmt(fmt) "ACPI: IORT: " fmt
#include <linux/acpi_iort.h> #include <linux/acpi_iort.h>
#include <linux/bitfield.h>
#include <linux/iommu.h> #include <linux/iommu.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/list.h> #include <linux/list.h>
...@@ -924,6 +925,20 @@ static int iort_pci_iommu_init(struct pci_dev *pdev, u16 alias, void *data) ...@@ -924,6 +925,20 @@ static int iort_pci_iommu_init(struct pci_dev *pdev, u16 alias, void *data)
return iort_iommu_xlate(info->dev, parent, streamid); return iort_iommu_xlate(info->dev, parent, streamid);
} }
static void iort_named_component_init(struct device *dev,
struct acpi_iort_node *node)
{
struct acpi_iort_named_component *nc;
struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
if (!fwspec)
return;
nc = (struct acpi_iort_named_component *)node->node_data;
fwspec->num_pasid_bits = FIELD_GET(ACPI_IORT_NC_PASID_BITS,
nc->node_flags);
}
/** /**
* iort_iommu_configure - Set-up IOMMU configuration for a device. * iort_iommu_configure - Set-up IOMMU configuration for a device.
* *
...@@ -978,6 +993,9 @@ const struct iommu_ops *iort_iommu_configure(struct device *dev) ...@@ -978,6 +993,9 @@ const struct iommu_ops *iort_iommu_configure(struct device *dev)
if (parent) if (parent)
err = iort_iommu_xlate(dev, parent, streamid); err = iort_iommu_xlate(dev, parent, streamid);
} while (parent && !err); } while (parent && !err);
if (!err)
iort_named_component_init(dev, node);
} }
/* /*
......
...@@ -119,7 +119,7 @@ int arm_mmu500_reset(struct arm_smmu_device *smmu) ...@@ -119,7 +119,7 @@ int arm_mmu500_reset(struct arm_smmu_device *smmu)
* Secure has also cleared SACR.CACHE_LOCK for this to take effect... * Secure has also cleared SACR.CACHE_LOCK for this to take effect...
*/ */
reg = arm_smmu_gr0_read(smmu, ARM_SMMU_GR0_ID7); reg = arm_smmu_gr0_read(smmu, ARM_SMMU_GR0_ID7);
major = FIELD_GET(ID7_MAJOR, reg); major = FIELD_GET(ARM_SMMU_ID7_MAJOR, reg);
reg = arm_smmu_gr0_read(smmu, ARM_SMMU_GR0_sACR); reg = arm_smmu_gr0_read(smmu, ARM_SMMU_GR0_sACR);
if (major >= 2) if (major >= 2)
reg &= ~ARM_MMU500_ACR_CACHE_LOCK; reg &= ~ARM_MMU500_ACR_CACHE_LOCK;
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -149,8 +149,6 @@ ...@@ -149,8 +149,6 @@
#define ARM_V7S_TTBR_IRGN_ATTR(attr) \ #define ARM_V7S_TTBR_IRGN_ATTR(attr) \
((((attr) & 0x1) << 6) | (((attr) & 0x2) >> 1)) ((((attr) & 0x1) << 6) | (((attr) & 0x2) >> 1))
#define ARM_V7S_TCR_PD1 BIT(5)
#ifdef CONFIG_ZONE_DMA32 #ifdef CONFIG_ZONE_DMA32
#define ARM_V7S_TABLE_GFP_DMA GFP_DMA32 #define ARM_V7S_TABLE_GFP_DMA GFP_DMA32
#define ARM_V7S_TABLE_SLAB_FLAGS SLAB_CACHE_DMA32 #define ARM_V7S_TABLE_SLAB_FLAGS SLAB_CACHE_DMA32
...@@ -798,8 +796,8 @@ static struct io_pgtable *arm_v7s_alloc_pgtable(struct io_pgtable_cfg *cfg, ...@@ -798,8 +796,8 @@ static struct io_pgtable *arm_v7s_alloc_pgtable(struct io_pgtable_cfg *cfg,
*/ */
cfg->pgsize_bitmap &= SZ_4K | SZ_64K | SZ_1M | SZ_16M; cfg->pgsize_bitmap &= SZ_4K | SZ_64K | SZ_1M | SZ_16M;
/* TCR: T0SZ=0, disable TTBR1 */ /* TCR: T0SZ=0, EAE=0 (if applicable) */
cfg->arm_v7s_cfg.tcr = ARM_V7S_TCR_PD1; cfg->arm_v7s_cfg.tcr = 0;
/* /*
* TEX remap: the indices used map to the closest equivalent types * TEX remap: the indices used map to the closest equivalent types
...@@ -822,15 +820,13 @@ static struct io_pgtable *arm_v7s_alloc_pgtable(struct io_pgtable_cfg *cfg, ...@@ -822,15 +820,13 @@ static struct io_pgtable *arm_v7s_alloc_pgtable(struct io_pgtable_cfg *cfg,
/* Ensure the empty pgd is visible before any actual TTBR write */ /* Ensure the empty pgd is visible before any actual TTBR write */
wmb(); wmb();
/* TTBRs */ /* TTBR */
cfg->arm_v7s_cfg.ttbr[0] = virt_to_phys(data->pgd) | cfg->arm_v7s_cfg.ttbr = virt_to_phys(data->pgd) | ARM_V7S_TTBR_S |
ARM_V7S_TTBR_S | ARM_V7S_TTBR_NOS | (cfg->coherent_walk ? (ARM_V7S_TTBR_NOS |
(cfg->coherent_walk ? ARM_V7S_TTBR_IRGN_ATTR(ARM_V7S_RGN_WBWA) |
(ARM_V7S_TTBR_IRGN_ATTR(ARM_V7S_RGN_WBWA) | ARM_V7S_TTBR_ORGN_ATTR(ARM_V7S_RGN_WBWA)) :
ARM_V7S_TTBR_ORGN_ATTR(ARM_V7S_RGN_WBWA)) : (ARM_V7S_TTBR_IRGN_ATTR(ARM_V7S_RGN_NC) |
(ARM_V7S_TTBR_IRGN_ATTR(ARM_V7S_RGN_NC) | ARM_V7S_TTBR_ORGN_ATTR(ARM_V7S_RGN_NC)));
ARM_V7S_TTBR_ORGN_ATTR(ARM_V7S_RGN_NC)));
cfg->arm_v7s_cfg.ttbr[1] = 0;
return &data->iop; return &data->iop;
out_free_data: out_free_data:
......
This diff is collapsed.
...@@ -63,7 +63,7 @@ void free_io_pgtable_ops(struct io_pgtable_ops *ops) ...@@ -63,7 +63,7 @@ void free_io_pgtable_ops(struct io_pgtable_ops *ops)
if (!ops) if (!ops)
return; return;
iop = container_of(ops, struct io_pgtable, ops); iop = io_pgtable_ops_to_pgtable(ops);
io_pgtable_tlb_flush_all(iop); io_pgtable_tlb_flush_all(iop);
io_pgtable_init_table[iop->fmt]->free(iop); io_pgtable_init_table[iop->fmt]->free(iop);
} }
......
...@@ -374,7 +374,7 @@ static void ipmmu_domain_setup_context(struct ipmmu_vmsa_domain *domain) ...@@ -374,7 +374,7 @@ static void ipmmu_domain_setup_context(struct ipmmu_vmsa_domain *domain)
u32 tmp; u32 tmp;
/* TTBR0 */ /* TTBR0 */
ttbr = domain->cfg.arm_lpae_s1_cfg.ttbr[0]; ttbr = domain->cfg.arm_lpae_s1_cfg.ttbr;
ipmmu_ctx_write_root(domain, IMTTLBR0, ttbr); ipmmu_ctx_write_root(domain, IMTTLBR0, ttbr);
ipmmu_ctx_write_root(domain, IMTTUBR0, ttbr >> 32); ipmmu_ctx_write_root(domain, IMTTUBR0, ttbr >> 32);
......
...@@ -279,8 +279,8 @@ static void __program_context(void __iomem *base, int ctx, ...@@ -279,8 +279,8 @@ static void __program_context(void __iomem *base, int ctx,
SET_V2PCFG(base, ctx, 0x3); SET_V2PCFG(base, ctx, 0x3);
SET_TTBCR(base, ctx, priv->cfg.arm_v7s_cfg.tcr); SET_TTBCR(base, ctx, priv->cfg.arm_v7s_cfg.tcr);
SET_TTBR0(base, ctx, priv->cfg.arm_v7s_cfg.ttbr[0]); SET_TTBR0(base, ctx, priv->cfg.arm_v7s_cfg.ttbr);
SET_TTBR1(base, ctx, priv->cfg.arm_v7s_cfg.ttbr[1]); SET_TTBR1(base, ctx, 0);
/* Set prrr and nmrr */ /* Set prrr and nmrr */
SET_PRRR(base, ctx, priv->cfg.arm_v7s_cfg.prrr); SET_PRRR(base, ctx, priv->cfg.arm_v7s_cfg.prrr);
......
...@@ -367,7 +367,7 @@ static int mtk_iommu_attach_device(struct iommu_domain *domain, ...@@ -367,7 +367,7 @@ static int mtk_iommu_attach_device(struct iommu_domain *domain,
/* Update the pgtable base address register of the M4U HW */ /* Update the pgtable base address register of the M4U HW */
if (!data->m4u_dom) { if (!data->m4u_dom) {
data->m4u_dom = dom; data->m4u_dom = dom;
writel(dom->cfg.arm_v7s_cfg.ttbr[0] & MMU_PT_ADDR_MASK, writel(dom->cfg.arm_v7s_cfg.ttbr & MMU_PT_ADDR_MASK,
data->base + REG_MMU_PT_BASE_ADDR); data->base + REG_MMU_PT_BASE_ADDR);
} }
...@@ -765,7 +765,7 @@ static int __maybe_unused mtk_iommu_resume(struct device *dev) ...@@ -765,7 +765,7 @@ static int __maybe_unused mtk_iommu_resume(struct device *dev)
writel_relaxed(reg->ivrp_paddr, base + REG_MMU_IVRP_PADDR); writel_relaxed(reg->ivrp_paddr, base + REG_MMU_IVRP_PADDR);
writel_relaxed(reg->vld_pa_rng, base + REG_MMU_VLD_PA_RNG); writel_relaxed(reg->vld_pa_rng, base + REG_MMU_VLD_PA_RNG);
if (m4u_dom) if (m4u_dom)
writel(m4u_dom->cfg.arm_v7s_cfg.ttbr[0] & MMU_PT_ADDR_MASK, writel(m4u_dom->cfg.arm_v7s_cfg.ttbr & MMU_PT_ADDR_MASK,
base + REG_MMU_PT_BASE_ADDR); base + REG_MMU_PT_BASE_ADDR);
return 0; return 0;
} }
......
...@@ -203,8 +203,12 @@ const struct iommu_ops *of_iommu_configure(struct device *dev, ...@@ -203,8 +203,12 @@ const struct iommu_ops *of_iommu_configure(struct device *dev,
if (err) if (err)
break; break;
} }
}
fwspec = dev_iommu_fwspec_get(dev);
if (!err && fwspec)
of_property_read_u32(master_np, "pasid-num-bits",
&fwspec->num_pasid_bits);
}
/* /*
* Two success conditions can be represented by non-negative err here: * Two success conditions can be represented by non-negative err here:
......
...@@ -201,7 +201,7 @@ static irqreturn_t qcom_iommu_fault(int irq, void *dev) ...@@ -201,7 +201,7 @@ static irqreturn_t qcom_iommu_fault(int irq, void *dev)
fsr = iommu_readl(ctx, ARM_SMMU_CB_FSR); fsr = iommu_readl(ctx, ARM_SMMU_CB_FSR);
if (!(fsr & FSR_FAULT)) if (!(fsr & ARM_SMMU_FSR_FAULT))
return IRQ_NONE; return IRQ_NONE;
fsynr = iommu_readl(ctx, ARM_SMMU_CB_FSYNR0); fsynr = iommu_readl(ctx, ARM_SMMU_CB_FSYNR0);
...@@ -215,7 +215,7 @@ static irqreturn_t qcom_iommu_fault(int irq, void *dev) ...@@ -215,7 +215,7 @@ static irqreturn_t qcom_iommu_fault(int irq, void *dev)
} }
iommu_writel(ctx, ARM_SMMU_CB_FSR, fsr); iommu_writel(ctx, ARM_SMMU_CB_FSR, fsr);
iommu_writel(ctx, ARM_SMMU_CB_RESUME, RESUME_TERMINATE); iommu_writel(ctx, ARM_SMMU_CB_RESUME, ARM_SMMU_RESUME_TERMINATE);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
...@@ -269,18 +269,15 @@ static int qcom_iommu_init_domain(struct iommu_domain *domain, ...@@ -269,18 +269,15 @@ static int qcom_iommu_init_domain(struct iommu_domain *domain,
/* TTBRs */ /* TTBRs */
iommu_writeq(ctx, ARM_SMMU_CB_TTBR0, iommu_writeq(ctx, ARM_SMMU_CB_TTBR0,
pgtbl_cfg.arm_lpae_s1_cfg.ttbr[0] | pgtbl_cfg.arm_lpae_s1_cfg.ttbr |
FIELD_PREP(TTBRn_ASID, ctx->asid)); FIELD_PREP(ARM_SMMU_TTBRn_ASID, ctx->asid));
iommu_writeq(ctx, ARM_SMMU_CB_TTBR1, iommu_writeq(ctx, ARM_SMMU_CB_TTBR1, 0);
pgtbl_cfg.arm_lpae_s1_cfg.ttbr[1] |
FIELD_PREP(TTBRn_ASID, ctx->asid));
/* TCR */ /* TCR */
iommu_writel(ctx, ARM_SMMU_CB_TCR2, iommu_writel(ctx, ARM_SMMU_CB_TCR2,
(pgtbl_cfg.arm_lpae_s1_cfg.tcr >> 32) | arm_smmu_lpae_tcr2(&pgtbl_cfg));
FIELD_PREP(TCR2_SEP, TCR2_SEP_UPSTREAM));
iommu_writel(ctx, ARM_SMMU_CB_TCR, iommu_writel(ctx, ARM_SMMU_CB_TCR,
pgtbl_cfg.arm_lpae_s1_cfg.tcr); arm_smmu_lpae_tcr(&pgtbl_cfg) | ARM_SMMU_TCR_EAE);
/* MAIRs (stage-1 only) */ /* MAIRs (stage-1 only) */
iommu_writel(ctx, ARM_SMMU_CB_S1_MAIR0, iommu_writel(ctx, ARM_SMMU_CB_S1_MAIR0,
...@@ -289,11 +286,13 @@ static int qcom_iommu_init_domain(struct iommu_domain *domain, ...@@ -289,11 +286,13 @@ static int qcom_iommu_init_domain(struct iommu_domain *domain,
pgtbl_cfg.arm_lpae_s1_cfg.mair >> 32); pgtbl_cfg.arm_lpae_s1_cfg.mair >> 32);
/* SCTLR */ /* SCTLR */
reg = SCTLR_CFIE | SCTLR_CFRE | SCTLR_AFE | SCTLR_TRE | reg = ARM_SMMU_SCTLR_CFIE | ARM_SMMU_SCTLR_CFRE |
SCTLR_M | SCTLR_S1_ASIDPNE | SCTLR_CFCFG; ARM_SMMU_SCTLR_AFE | ARM_SMMU_SCTLR_TRE |
ARM_SMMU_SCTLR_M | ARM_SMMU_SCTLR_S1_ASIDPNE |
ARM_SMMU_SCTLR_CFCFG;
if (IS_ENABLED(CONFIG_BIG_ENDIAN)) if (IS_ENABLED(CONFIG_BIG_ENDIAN))
reg |= SCTLR_E; reg |= ARM_SMMU_SCTLR_E;
iommu_writel(ctx, ARM_SMMU_CB_SCTLR, reg); iommu_writel(ctx, ARM_SMMU_CB_SCTLR, reg);
......
...@@ -83,12 +83,16 @@ struct io_pgtable_cfg { ...@@ -83,12 +83,16 @@ struct io_pgtable_cfg {
* IO_PGTABLE_QUIRK_NON_STRICT: Skip issuing synchronous leaf TLBIs * IO_PGTABLE_QUIRK_NON_STRICT: Skip issuing synchronous leaf TLBIs
* on unmap, for DMA domains using the flush queue mechanism for * on unmap, for DMA domains using the flush queue mechanism for
* delayed invalidation. * delayed invalidation.
*
* IO_PGTABLE_QUIRK_ARM_TTBR1: (ARM LPAE format) Configure the table
* for use in the upper half of a split address space.
*/ */
#define IO_PGTABLE_QUIRK_ARM_NS BIT(0) #define IO_PGTABLE_QUIRK_ARM_NS BIT(0)
#define IO_PGTABLE_QUIRK_NO_PERMS BIT(1) #define IO_PGTABLE_QUIRK_NO_PERMS BIT(1)
#define IO_PGTABLE_QUIRK_TLBI_ON_MAP BIT(2) #define IO_PGTABLE_QUIRK_TLBI_ON_MAP BIT(2)
#define IO_PGTABLE_QUIRK_ARM_MTK_EXT BIT(3) #define IO_PGTABLE_QUIRK_ARM_MTK_EXT BIT(3)
#define IO_PGTABLE_QUIRK_NON_STRICT BIT(4) #define IO_PGTABLE_QUIRK_NON_STRICT BIT(4)
#define IO_PGTABLE_QUIRK_ARM_TTBR1 BIT(5)
unsigned long quirks; unsigned long quirks;
unsigned long pgsize_bitmap; unsigned long pgsize_bitmap;
unsigned int ias; unsigned int ias;
...@@ -100,18 +104,33 @@ struct io_pgtable_cfg { ...@@ -100,18 +104,33 @@ struct io_pgtable_cfg {
/* Low-level data specific to the table format */ /* Low-level data specific to the table format */
union { union {
struct { struct {
u64 ttbr[2]; u64 ttbr;
u64 tcr; struct {
u32 ips:3;
u32 tg:2;
u32 sh:2;
u32 orgn:2;
u32 irgn:2;
u32 tsz:6;
} tcr;
u64 mair; u64 mair;
} arm_lpae_s1_cfg; } arm_lpae_s1_cfg;
struct { struct {
u64 vttbr; u64 vttbr;
u64 vtcr; struct {
u32 ps:3;
u32 tg:2;
u32 sh:2;
u32 orgn:2;
u32 irgn:2;
u32 sl:2;
u32 tsz:6;
} vtcr;
} arm_lpae_s2_cfg; } arm_lpae_s2_cfg;
struct { struct {
u32 ttbr[2]; u32 ttbr;
u32 tcr; u32 tcr;
u32 nmrr; u32 nmrr;
u32 prrr; u32 prrr;
......
...@@ -388,12 +388,19 @@ void iommu_device_sysfs_remove(struct iommu_device *iommu); ...@@ -388,12 +388,19 @@ void iommu_device_sysfs_remove(struct iommu_device *iommu);
int iommu_device_link(struct iommu_device *iommu, struct device *link); int iommu_device_link(struct iommu_device *iommu, struct device *link);
void iommu_device_unlink(struct iommu_device *iommu, struct device *link); void iommu_device_unlink(struct iommu_device *iommu, struct device *link);
static inline void iommu_device_set_ops(struct iommu_device *iommu, static inline void __iommu_device_set_ops(struct iommu_device *iommu,
const struct iommu_ops *ops) const struct iommu_ops *ops)
{ {
iommu->ops = ops; iommu->ops = ops;
} }
#define iommu_device_set_ops(iommu, ops) \
do { \
struct iommu_ops *__ops = (struct iommu_ops *)(ops); \
__ops->owner = THIS_MODULE; \
__iommu_device_set_ops(iommu, __ops); \
} while (0)
static inline void iommu_device_set_fwnode(struct iommu_device *iommu, static inline void iommu_device_set_fwnode(struct iommu_device *iommu,
struct fwnode_handle *fwnode) struct fwnode_handle *fwnode)
{ {
...@@ -572,6 +579,7 @@ struct iommu_group *fsl_mc_device_group(struct device *dev); ...@@ -572,6 +579,7 @@ struct iommu_group *fsl_mc_device_group(struct device *dev);
* @ops: ops for this device's IOMMU * @ops: ops for this device's IOMMU
* @iommu_fwnode: firmware handle for this device's IOMMU * @iommu_fwnode: firmware handle for this device's IOMMU
* @iommu_priv: IOMMU driver private data for this device * @iommu_priv: IOMMU driver private data for this device
* @num_pasid_bits: number of PASID bits supported by this device
* @num_ids: number of associated device IDs * @num_ids: number of associated device IDs
* @ids: IDs which this device may present to the IOMMU * @ids: IDs which this device may present to the IOMMU
*/ */
...@@ -580,6 +588,7 @@ struct iommu_fwspec { ...@@ -580,6 +588,7 @@ struct iommu_fwspec {
struct fwnode_handle *iommu_fwnode; struct fwnode_handle *iommu_fwnode;
void *iommu_priv; void *iommu_priv;
u32 flags; u32 flags;
u32 num_pasid_bits;
unsigned int num_ids; unsigned int num_ids;
u32 ids[1]; u32 ids[1];
}; };
......
...@@ -33,6 +33,9 @@ void pci_disable_pasid(struct pci_dev *pdev); ...@@ -33,6 +33,9 @@ void pci_disable_pasid(struct pci_dev *pdev);
int pci_pasid_features(struct pci_dev *pdev); int pci_pasid_features(struct pci_dev *pdev);
int pci_max_pasids(struct pci_dev *pdev); int pci_max_pasids(struct pci_dev *pdev);
#else /* CONFIG_PCI_PASID */ #else /* CONFIG_PCI_PASID */
static inline int pci_enable_pasid(struct pci_dev *pdev, int features)
{ return -EINVAL; }
static inline void pci_disable_pasid(struct pci_dev *pdev) { }
static inline int pci_pasid_features(struct pci_dev *pdev) static inline int pci_pasid_features(struct pci_dev *pdev)
{ return -EINVAL; } { return -EINVAL; }
static inline int pci_max_pasids(struct pci_dev *pdev) static inline int pci_max_pasids(struct pci_dev *pdev)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment