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

Commit 5fe870f7 authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "arm-smmu: add bitmap for secure context banks"

parents 998f63b8 df3884cb
Loading
Loading
Loading
Loading
+53 −2
Original line number Diff line number Diff line
@@ -273,6 +273,7 @@ struct arm_smmu_device {
	u32				num_context_banks;
	u32				num_s2_context_banks;
	DECLARE_BITMAP(context_map, ARM_SMMU_MAX_CBS);
	DECLARE_BITMAP(secure_context_map, ARM_SMMU_MAX_CBS);
	struct arm_smmu_cb		*cbs;
	atomic_t			irptndx;

@@ -2785,6 +2786,11 @@ static void arm_smmu_destroy_domain_context(struct iommu_domain *domain)
	arm_smmu_unassign_table(smmu_domain);
	arm_smmu_secure_domain_unlock(smmu_domain);
	__arm_smmu_free_bitmap(smmu->context_map, cfg->cbndx);
	/* As the nonsecure context bank index is any way set to zero,
	 * so, directly clearing up the secure cb bitmap.
	 */
	if (arm_smmu_is_slave_side_secure(smmu_domain))
		__arm_smmu_free_bitmap(smmu->secure_context_map, cfg->cbndx);

	arm_smmu_power_off(smmu->pwr);
	arm_smmu_domain_reinit(smmu_domain);
@@ -3916,6 +3922,46 @@ static size_t msm_secure_smmu_map_sg(struct iommu_domain *domain,
	return ret;
}

void *get_smmu_from_addr(struct iommu_device *iommu, void __iomem *addr)
{
	struct arm_smmu_device *smmu = NULL;
	unsigned long base, mask;

	smmu = arm_smmu_get_by_fwnode(iommu->fwnode);
	if (!smmu)
		return NULL;

	base = (unsigned long)smmu->base;
	mask = ~(smmu->size - 1);

	if ((base & mask) == ((unsigned long)addr & mask))
		return (void *)smmu;

	return NULL;
}

bool arm_smmu_skip_write(void __iomem *addr)
{
	struct arm_smmu_device *smmu;
	int cb;

	smmu = arm_smmu_get_by_addr(addr);

	/* 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;
	if (test_bit(cb, smmu->secure_context_map))
		return true;

	return false;
}
#endif

static int arm_smmu_add_device(struct device *dev)
@@ -4956,9 +5002,13 @@ 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))
			bitmap_set(smmu->secure_context_map, cb, 1);
	}

	if (cb < 0 && !arm_smmu_is_static_cb(smmu)) {
		mutex_unlock(&smmu->stream_map_mutex);
		return __arm_smmu_alloc_bitmap(smmu->context_map,
@@ -5765,7 +5815,8 @@ static int arm_smmu_device_remove(struct platform_device *pdev)
	if (arm_smmu_power_on(smmu->pwr))
		return -EINVAL;

	if (!bitmap_empty(smmu->context_map, ARM_SMMU_MAX_CBS))
	if (!bitmap_empty(smmu->context_map, ARM_SMMU_MAX_CBS) ||
	    !bitmap_empty(smmu->secure_context_map, ARM_SMMU_MAX_CBS))
		dev_err(&pdev->dev, "removing device with active domains!\n");

	idr_destroy(&smmu->asid_idr);
+23 −0
Original line number Diff line number Diff line
@@ -34,6 +34,9 @@
#include <linux/debugfs.h>
#include <linux/property.h>
#include <trace/events/iommu.h>
#ifdef CONFIG_MSM_TZ_SMMU
#include <soc/qcom/msm_tz_smmu.h>
#endif

static struct kset *iommu_group_kset;
static DEFINE_IDA(iommu_group_ida);
@@ -133,6 +136,26 @@ void iommu_device_unregister(struct iommu_device *iommu)
	spin_unlock(&iommu_device_lock);
}

#ifdef CONFIG_MSM_TZ_SMMU
void *arm_smmu_get_by_addr(void __iomem *addr)
{
	struct iommu_device *iommu;
	unsigned long flags;
	void *smmu = NULL;

	spin_lock_irqsave(&iommu_device_lock, flags);
	list_for_each_entry(iommu, &iommu_device_list, list) {
		smmu = get_smmu_from_addr(iommu, addr);
		if (!smmu)
			continue;
		break;
	}
	spin_unlock_irqrestore(&iommu_device_lock, flags);

	return smmu;
}
#endif

static struct iommu_domain *__iommu_domain_alloc(struct bus_type *bus,
						 unsigned type);
static int __iommu_attach_device(struct iommu_domain *domain,
+12 −1
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
 * Copyright (c) 2015-2018,2021, The Linux Foundation. All rights reserved.
 */

#ifndef __MSM_TZ_SMMU_H__
#define __MSM_TZ_SMMU_H__

#include <linux/device.h>
#include <linux/iommu.h>

enum tz_smmu_device_id {
	TZ_DEVICE_START = 0,
@@ -49,6 +50,16 @@ enum tz_smmu_device_id msm_dev_to_device_id(struct device *dev);
int msm_tz_set_cb_format(enum tz_smmu_device_id sec_id, int cbndx);
int msm_iommu_sec_pgtbl_init(void);
int register_iommu_sec_ptbl(void);
bool arm_smmu_skip_write(void __iomem *addr);
extern void *get_smmu_from_addr(struct iommu_device *iommu, void __iomem *addr);
extern void *arm_smmu_get_by_addr(void __iomem *addr);
/* Donot write to smmu global space with CONFIG_MSM_TZ_SMMU */
#undef writel_relaxed
#define writel_relaxed(v, c)	do {					\
	if (!arm_smmu_skip_write(c))					\
		((void)__raw_writel((u32)cpu_to_le32(v), (c)));	\
	} while (0)

#else

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