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

Commit a28a4791 authored by Shiraz Hashim's avatar Shiraz Hashim Committed by Charan Teja Reddy
Browse files

iommu/arm-smmu: Do not write to slave side protected context banks



For msm targets that have slave side access control, iommu
driver is not allowed to write to secure context bank
register space. Extend arm_smmu_skip_write logic to
consider such protected context bank address space as well
for skipping.

Change-Id: Ia64ab5a1c7f8b4ced82f25ab0d2988ac8d08aec3
Signed-off-by: default avatarShiraz Hashim <shashim@codeaurora.org>
Signed-off-by: default avatarCharan Teja Reddy <charante@codeaurora.org>
parent 40dd625b
Loading
Loading
Loading
Loading
+27 −5
Original line number Diff line number Diff line
@@ -355,11 +355,13 @@ struct arm_smmu_s2cr {
	enum arm_smmu_s2cr_privcfg	privcfg;
	u8				cbndx;
	bool				cb_handoff;
	bool				write_protected;
};

#define s2cr_init_val (struct arm_smmu_s2cr){				\
	.type = disable_bypass ? S2CR_TYPE_FAULT : S2CR_TYPE_BYPASS,	\
	.cb_handoff = false,						\
	.write_protected = false,					\
}

struct arm_smmu_smr {
@@ -2758,14 +2760,29 @@ static struct arm_smmu_device *arm_smmu_get_by_addr(void __iomem *addr)
bool arm_smmu_skip_write(void __iomem *addr)
{
	struct arm_smmu_device *smmu;
	unsigned long cb;
	int i;

	smmu = arm_smmu_get_by_addr(addr);
	if (smmu &&
	    ((unsigned long)addr & (smmu->size - 1)) >= (smmu->size >> 1))
		return false;
	else

	/* Skip write if smmu not available by now */
	if (!smmu)
		return true;

	/* Do not write to global space */
	if (((unsigned long)addr & (smmu->size - 1)) < (smmu->size >> 1))
		return true;

	/* Finally skip writing to secure CB */
	cb = ((unsigned long)addr & ((smmu->size >> 1) - 1)) >> PAGE_SHIFT;
	for (i = 0; i < smmu->num_mapping_groups; i++) {
		if ((smmu->s2crs[i].cbndx == cb) &&
		    (smmu->s2crs[i].write_protected))
			return true;
	}

	return false;
}
#endif

static struct arm_smmu_device *arm_smmu_get_by_list(struct device_node *np)
@@ -3698,9 +3715,14 @@ static int arm_smmu_alloc_cb(struct iommu_domain *domain,
			cb = smmu->s2crs[idx].cbndx;
	}

	if (cb >= 0 && arm_smmu_is_static_cb(smmu))
	if (cb >= 0 && arm_smmu_is_static_cb(smmu)) {
		smmu_domain->slave_side_secure = true;

		if (arm_smmu_is_slave_side_secure(smmu_domain))
			for_each_cfg_sme(fwspec, i, idx)
				smmu->s2crs[idx].write_protected = true;
	}

	if (cb < 0 && !arm_smmu_is_static_cb(smmu)) {
		mutex_unlock(&smmu->stream_map_mutex);
		return __arm_smmu_alloc_bitmap(smmu->context_map,
+6 −1
Original line number Diff line number Diff line
/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -60,11 +60,16 @@ bool arm_smmu_skip_write(void __iomem *addr);

/* Donot write to smmu global space with CONFIG_MSM_TZ_SMMU */
#undef writel_relaxed
#undef writeq_relaxed
#define writel_relaxed(v, c)	do {					\
	if (!arm_smmu_skip_write(c))					\
		((void)__raw_writel((__force u32)cpu_to_le32(v), (c)));	\
	} while (0)

#define writeq_relaxed(v, c) do {					\
	if (!arm_smmu_skip_write(c))					\
		((void)__raw_writeq((__force u64)cpu_to_le64(v), (c)));	\
	} while (0)
#else

static inline int msm_tz_smmu_atos_start(struct device *dev, int cb_num)