Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 21b8aa0b authored by qctecmdr Service's avatar qctecmdr Service Committed by Gerrit - the friendly Code Review server
Browse files

Merge "iommu: io-pgtable-arm: Implement IOMMU_USE_LLC_NWA"

parents 6df4590a 0d9a0c2d
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -156,3 +156,10 @@ accesses to DMA buffers in both privileged "supervisor" and unprivileged
subsystem that the buffer is fully accessible at the elevated privilege
level (and ideally inaccessible or at least read-only at the
lesser-privileged levels).

DMA_ATTR_IOMMU_USE_LLC_NWA
------------------------------------

DMA_ATTR_IOMMU_USE_LLC_NWA: Overrides the bus attributes to use
System Cache(LLC) with allocation policy as Inner Non-Cacheable, Outer Cacheable:
Write-Back, Read-Allocate, No Write-Allocate policy.
 No newline at end of file
+2 −0
Original line number Diff line number Diff line
@@ -1092,6 +1092,8 @@ static int __get_iommu_pgprot(unsigned long attrs, int prot,
		prot |= IOMMU_NOEXEC;
	if (attrs & DMA_ATTR_IOMMU_USE_UPSTREAM_HINT)
		prot |= IOMMU_USE_UPSTREAM_HINT;
	if (attrs & DMA_ATTR_IOMMU_USE_LLC_NWA)
		prot |= IOMMU_USE_LLC_NWA;
	if (coherent)
		prot |= IOMMU_CACHE;

+20 −1
Original line number Diff line number Diff line
@@ -1679,7 +1679,10 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain,
		quirks |= IO_PGTABLE_QUIRK_QCOM_USE_UPSTREAM_HINT;
	if (is_iommu_pt_coherent(smmu_domain))
		quirks |= IO_PGTABLE_QUIRK_NO_DMA;
	if ((quirks & IO_PGTABLE_QUIRK_QCOM_USE_UPSTREAM_HINT) &&
	if (smmu_domain->attributes & (1 << DOMAIN_ATTR_USE_LLC_NWA))
		quirks |= IO_PGTABLE_QUIRK_QCOM_USE_LLC_NWA;
	if (((quirks & IO_PGTABLE_QUIRK_QCOM_USE_UPSTREAM_HINT) ||
	     (quirks & IO_PGTABLE_QUIRK_QCOM_USE_LLC_NWA)) &&
		(smmu->model == QCOM_SMMUV500))
		quirks |= IO_PGTABLE_QUIRK_QSMMUV500_NON_SHAREABLE;

@@ -2819,6 +2822,11 @@ static int arm_smmu_domain_get_attr(struct iommu_domain *domain,
				   (1 << DOMAIN_ATTR_USE_UPSTREAM_HINT));
		ret = 0;
		break;
	case DOMAIN_ATTR_USE_LLC_NWA:
		*((int *)data) = !!(smmu_domain->attributes &
				   (1 << DOMAIN_ATTR_USE_LLC_NWA));
		ret = 0;
		break;
	case DOMAIN_ATTR_EARLY_MAP:
		*((int *)data) = !!(smmu_domain->attributes
				    & (1 << DOMAIN_ATTR_EARLY_MAP));
@@ -3001,6 +3009,17 @@ static int arm_smmu_domain_set_attr(struct iommu_domain *domain,
				1 << DOMAIN_ATTR_USE_UPSTREAM_HINT;
		ret = 0;
		break;
	case DOMAIN_ATTR_USE_LLC_NWA:
		/* can't be changed while attached */
		if (smmu_domain->smmu != NULL) {
			ret = -EBUSY;
			break;
		}
		if (*((int *)data))
			smmu_domain->attributes |=
				1 << DOMAIN_ATTR_USE_LLC_NWA;
		ret = 0;
		break;
	case DOMAIN_ATTR_EARLY_MAP: {
		int early_map = *((int *)data);

+3 −0
Original line number Diff line number Diff line
@@ -381,6 +381,9 @@ int dma_info_to_prot(enum dma_data_direction dir, bool coherent,
	if (attrs & DMA_ATTR_IOMMU_USE_UPSTREAM_HINT)
		prot |= IOMMU_USE_UPSTREAM_HINT;

	if (attrs & DMA_ATTR_IOMMU_USE_LLC_NWA)
		prot |= IOMMU_USE_LLC_NWA;

	switch (dir) {
	case DMA_BIDIRECTIONAL:
		return prot | IOMMU_READ | IOMMU_WRITE;
+22 −2
Original line number Diff line number Diff line
@@ -169,15 +169,18 @@
#define ARM_LPAE_TCR_PS_48_BIT		0x5ULL

#define ARM_LPAE_MAIR_ATTR_SHIFT(n)	((n) << 3)
#define ARM_LPAE_MAIR1_ATTR_SHIFT(n)	((n-4) << 3)
#define ARM_LPAE_MAIR_ATTR_MASK		0xff
#define ARM_LPAE_MAIR_ATTR_DEVICE	0x04
#define ARM_LPAE_MAIR_ATTR_NC		0x44
#define ARM_LPAE_MAIR_ATTR_WBRWA	0xff
#define ARM_LPAE_MAIR_ATTR_UPSTREAM	0xf4
#define ARM_LPAE_MAIR_ATTR_LLC_NWA	0xe4
#define ARM_LPAE_MAIR_ATTR_IDX_NC	0
#define ARM_LPAE_MAIR_ATTR_IDX_CACHE	1
#define ARM_LPAE_MAIR_ATTR_IDX_DEV	2
#define ARM_LPAE_MAIR_ATTR_IDX_UPSTREAM	3
#define ARM_LPAE_MAIR_ATTR_IDX_LLC_NWA	0x4ULL

/* IOPTE accessors */
#define iopte_deref(pte, d)						\
@@ -583,6 +586,9 @@ static arm_lpae_iopte arm_lpae_prot_to_pte(struct arm_lpae_io_pgtable *data,
		else if (prot & IOMMU_USE_UPSTREAM_HINT)
			pte |= (ARM_LPAE_MAIR_ATTR_IDX_UPSTREAM
				<< ARM_LPAE_PTE_ATTRINDX_SHIFT);
		else if (prot & IOMMU_USE_LLC_NWA)
			pte |= (ARM_LPAE_MAIR_ATTR_IDX_LLC_NWA
				<< ARM_LPAE_PTE_ATTRINDX_SHIFT);
	} else {
		pte = ARM_LPAE_PTE_HAP_FAULT;
		if (prot & IOMMU_READ)
@@ -1117,7 +1123,8 @@ arm_64_lpae_alloc_pgtable_s1(struct io_pgtable_cfg *cfg, void *cookie)
	if (cfg->quirks & ~(IO_PGTABLE_QUIRK_ARM_NS
			  | IO_PGTABLE_QUIRK_NO_DMA
			  | IO_PGTABLE_QUIRK_QCOM_USE_UPSTREAM_HINT
			  | IO_PGTABLE_QUIRK_QSMMUV500_NON_SHAREABLE))
			  | IO_PGTABLE_QUIRK_QSMMUV500_NON_SHAREABLE
			  | IO_PGTABLE_QUIRK_QCOM_USE_LLC_NWA))
		return NULL;

	data = arm_lpae_alloc_pgtable(cfg);
@@ -1138,6 +1145,15 @@ arm_64_lpae_alloc_pgtable_s1(struct io_pgtable_cfg *cfg, void *cookie)
		reg = (ARM_LPAE_TCR_SH_OS << ARM_LPAE_TCR_SH0_SHIFT) |
			(ARM_LPAE_TCR_RGN_NC << ARM_LPAE_TCR_IRGN0_SHIFT) |
			(ARM_LPAE_TCR_RGN_WBWA << ARM_LPAE_TCR_ORGN0_SHIFT);
	else if ((cfg->quirks & IO_PGTABLE_QUIRK_QCOM_USE_LLC_NWA) &&
		(cfg->quirks & IO_PGTABLE_QUIRK_QSMMUV500_NON_SHAREABLE))
		reg = (ARM_LPAE_TCR_SH_NS << ARM_LPAE_TCR_SH0_SHIFT) |
			(ARM_LPAE_TCR_RGN_NC << ARM_LPAE_TCR_IRGN0_SHIFT) |
			(ARM_LPAE_TCR_RGN_WB << ARM_LPAE_TCR_ORGN0_SHIFT);
	else if (cfg->quirks & IO_PGTABLE_QUIRK_QCOM_USE_LLC_NWA)
		reg = (ARM_LPAE_TCR_SH_OS << ARM_LPAE_TCR_SH0_SHIFT) |
			(ARM_LPAE_TCR_RGN_NC << ARM_LPAE_TCR_IRGN0_SHIFT) |
			(ARM_LPAE_TCR_RGN_WB << ARM_LPAE_TCR_ORGN0_SHIFT);
	else
		reg = (ARM_LPAE_TCR_SH_OS << ARM_LPAE_TCR_SH0_SHIFT) |
			(ARM_LPAE_TCR_RGN_NC << ARM_LPAE_TCR_IRGN0_SHIFT) |
@@ -1195,7 +1211,11 @@ arm_64_lpae_alloc_pgtable_s1(struct io_pgtable_cfg *cfg, void *cookie)
	       << ARM_LPAE_MAIR_ATTR_SHIFT(ARM_LPAE_MAIR_ATTR_IDX_UPSTREAM));

	cfg->arm_lpae_s1_cfg.mair[0] = reg;
	cfg->arm_lpae_s1_cfg.mair[1] = 0;

	reg = ARM_LPAE_MAIR_ATTR_LLC_NWA
	      << ARM_LPAE_MAIR1_ATTR_SHIFT(ARM_LPAE_MAIR_ATTR_IDX_LLC_NWA);

	cfg->arm_lpae_s1_cfg.mair[1] = reg;

	/* Looking good; allocate a pgd */
	data->pgd = __arm_lpae_alloc_pages(data->pgd_size, GFP_KERNEL,
Loading