From 1ed8d78adb1368acb1c143cb3f570ab53ed0adb6 Mon Sep 17 00:00:00 2001
From: James Morse <james.morse@arm.com>
Date: Thu, 16 Sep 2021 16:50:46 +0100
Subject: [PATCH] arm_mpam: resctrl: Add iommu helpers to get/set the partid
 and pmg

SMMU that support MPAM can be configured to use a particular partid
and pmg for a stream. The assignment of an iommu_group and its
corresponding streams should be done via resctrl.

Add helpers similar to setting a closid/rmid on a task. We need
the same shifting if the CPUs are using CDP. The SMMU only takes
one partid, conceptually its always making data accesses.

Signed-off-by: James Morse <james.morse@arm.com>
---
 drivers/platform/mpam/Kconfig        |  1 +
 drivers/platform/mpam/mpam_resctrl.c | 62 ++++++++++++++++++++++++++++
 include/linux/arm_mpam.h             |  6 +++
 3 files changed, 69 insertions(+)

diff --git a/drivers/platform/mpam/Kconfig b/drivers/platform/mpam/Kconfig
index 75f5b2454fbe4..96dd7c091a9fc 100644
--- a/drivers/platform/mpam/Kconfig
+++ b/drivers/platform/mpam/Kconfig
@@ -6,3 +6,4 @@ config ARM_CPU_RESCTRL
 	depends on ARM64 && ARCH_HAS_CPU_RESCTRL
 	depends on MISC_FILESYSTEMS
 	select RESCTRL_RMID_DEPENDS_ON_CLOSID
+	select RESCTRL_IOMMU if ARM_SMMU_V3
diff --git a/drivers/platform/mpam/mpam_resctrl.c b/drivers/platform/mpam/mpam_resctrl.c
index 7bf0186de6575..60de4b0927bf9 100644
--- a/drivers/platform/mpam/mpam_resctrl.c
+++ b/drivers/platform/mpam/mpam_resctrl.c
@@ -8,6 +8,7 @@
 #include <linux/cpu.h>
 #include <linux/cpumask.h>
 #include <linux/errno.h>
+#include <linux/iommu.h>
 #include <linux/limits.h>
 #include <linux/list.h>
 #include <linux/printk.h>
@@ -212,6 +213,67 @@ bool resctrl_arch_match_rmid(struct task_struct *tsk, u32 closid, u32 rmid)
 	return (tsk_closid == closid) && (tsk_rmid == rmid);
 }
 
+int resctrl_arch_set_iommu_closid_rmid(struct iommu_group *group, u32 closid,
+					u32 rmid)
+{
+	u16 partid;
+	const struct iommu_ops *ops;
+
+	ops = iommu_group_get_ops(group);
+	if (!ops || !ops->set_group_qos_params)
+		return -EOPNOTSUPP;
+
+	if (cdp_enabled)
+		partid = closid << 1;
+	else
+		partid = closid;
+
+	return ops->set_group_qos_params(group, partid, rmid);
+}
+
+bool resctrl_arch_match_iommu_closid(struct iommu_group *group, u32 closid)
+{
+	u16 partid;
+	int err = -EINVAL;
+	const struct iommu_ops *ops;
+
+	ops = iommu_group_get_ops(group);
+	if (!ops || !ops->get_group_qos_params)
+		return false;
+
+	err = ops->get_group_qos_params(group, &partid, NULL);
+	if (err)
+		return false;
+
+	if (cdp_enabled)
+		partid >>= 1;
+
+	return (partid == closid);
+}
+
+bool resctrl_arch_match_iommu_closid_rmid(struct iommu_group *group,
+					  u32 closid, u32 rmid)
+{
+	u8 pmg;
+	u16 partid;
+	int err = -EINVAL;
+	const struct iommu_ops *ops;
+
+	ops = iommu_group_get_ops(group);
+	if (!ops || !ops->get_group_qos_params)
+		return false;
+
+	err = ops->get_group_qos_params(group, &partid, &pmg);
+	if (err)
+		return false;
+
+	if (cdp_enabled)
+		partid >>= 1;
+
+	return (partid == closid) && (rmid == pmg);
+}
+
+
 struct rdt_resource *resctrl_arch_get_resource(enum resctrl_res_level l)
 {
 	if (l >= RDT_NUM_RESOURCES)
diff --git a/include/linux/arm_mpam.h b/include/linux/arm_mpam.h
index 3e3215223d79a..6d861ec69ce3a 100644
--- a/include/linux/arm_mpam.h
+++ b/include/linux/arm_mpam.h
@@ -82,6 +82,12 @@ struct rdt_resource;
 int resctrl_arch_mon_ctx_alloc_no_wait(struct rdt_resource *r, int evtid);
 void resctrl_arch_mon_ctx_free(struct rdt_resource *r, int evtid, int ctx);
 
+int resctrl_arch_set_iommu_closid_rmid(struct iommu_group *group, u32 closid,
+				       u32 rmid);
+bool resctrl_arch_match_iommu_closid(struct iommu_group *group, u32 closid);
+bool resctrl_arch_match_iommu_closid_rmid(struct iommu_group *group, u32 closid,
+					  u32 rmid);
+
 /* Pseudo lock is not supported by MPAM */
 static inline int resctrl_arch_pseudo_lock_fn(void *_plr) { return 0; }
 static inline int resctrl_arch_measure_l2_residency(void *_plr) { return 0; }
-- 
GitLab