[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20241212180423.1578358-37-smostafa@google.com>
Date: Thu, 12 Dec 2024 18:04:00 +0000
From: Mostafa Saleh <smostafa@...gle.com>
To: iommu@...ts.linux.dev, kvmarm@...ts.linux.dev,
linux-kernel@...r.kernel.org, linux-arm-kernel@...ts.infradead.org
Cc: catalin.marinas@....com, will@...nel.org, maz@...nel.org,
oliver.upton@...ux.dev, joey.gouly@....com, suzuki.poulose@....com,
yuzenghui@...wei.com, robdclark@...il.com, joro@...tes.org,
robin.murphy@....com, jean-philippe@...aro.org, jgg@...pe.ca,
nicolinc@...dia.com, vdonnefort@...gle.com, qperret@...gle.com,
tabba@...gle.com, danielmentz@...gle.com, tzukui@...gle.com,
Mostafa Saleh <smostafa@...gle.com>
Subject: [RFC PATCH v2 36/58] KVM: arm64: smmu-v3: Add detach_dev
Add detach_dev for stage-1 and stage-2 domains.
Signed-off-by: Mostafa Saleh <smostafa@...gle.com>
---
arch/arm64/kvm/hyp/nvhe/iommu/arm-smmu-v3.c | 76 ++++++++++++++++++++-
1 file changed, 75 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/kvm/hyp/nvhe/iommu/arm-smmu-v3.c b/arch/arm64/kvm/hyp/nvhe/iommu/arm-smmu-v3.c
index a96eb6625c48..ec3f8d9749d3 100644
--- a/arch/arm64/kvm/hyp/nvhe/iommu/arm-smmu-v3.c
+++ b/arch/arm64/kvm/hyp/nvhe/iommu/arm-smmu-v3.c
@@ -335,7 +335,6 @@ static u64 *smmu_alloc_cd(struct hyp_arm_smmu_v3_device *smmu, u32 pasid_bits)
return (u64 *)hyp_virt_to_phys(cd_table);
}
-__maybe_unused
static void smmu_free_cd(u64 *cd_table, u32 pasid_bits)
{
u32 order = get_order((1 << pasid_bits) *
@@ -1052,6 +1051,80 @@ static int smmu_attach_dev(struct kvm_hyp_iommu *iommu, struct kvm_hyp_iommu_dom
return ret;
}
+static int smmu_detach_dev(struct kvm_hyp_iommu *iommu, struct kvm_hyp_iommu_domain *domain,
+ u32 sid, u32 pasid)
+{
+ struct arm_smmu_ste *dst;
+ int i, ret;
+ struct hyp_arm_smmu_v3_device *smmu = to_smmu(iommu);
+ struct hyp_arm_smmu_v3_domain *smmu_domain = domain->priv;
+ u32 pasid_bits = 0;
+ u64 *cd_table, *cd;
+
+ kvm_iommu_lock(iommu);
+ dst = smmu_get_ste_ptr(smmu, sid);
+ if (!dst) {
+ ret = -ENODEV;
+ goto out_unlock;
+ }
+
+ /*
+ * For stage-1:
+ * - The kernel has to detach pasid = 0 the last.
+ * - This will free the CD.
+ */
+ if (smmu_domain->type == KVM_ARM_SMMU_DOMAIN_S1) {
+ pasid_bits = FIELD_GET(STRTAB_STE_0_S1CDMAX, dst->data[0]);
+ if (pasid >= (1 << pasid_bits)) {
+ ret = -E2BIG;
+ goto out_unlock;
+ }
+ cd_table = (u64 *)(dst->data[0] & STRTAB_STE_0_S1CTXPTR_MASK);
+ if (WARN_ON(!cd_table)) {
+ ret = -ENODEV;
+ goto out_unlock;
+ }
+
+ cd_table = hyp_phys_to_virt((phys_addr_t)cd_table);
+ if (pasid == 0) {
+ int j;
+
+ /* Ensure other pasids are detached. */
+ for (j = 1 ; j < (1 << pasid_bits) ; ++j) {
+ cd = smmu_get_cd_ptr(cd_table, j);
+ if (cd[0] & CTXDESC_CD_0_V) {
+ ret = -EINVAL;
+ goto out_unlock;
+ }
+ }
+ } else {
+ cd = smmu_get_cd_ptr(cd_table, pasid);
+ cd[0] = 0;
+ smmu_sync_cd(smmu, sid, pasid);
+ cd[1] = 0;
+ cd[2] = 0;
+ cd[3] = 0;
+ ret = smmu_sync_cd(smmu, sid, pasid);
+ goto out_unlock;
+ }
+ }
+ /* For stage-2 and pasid = 0 */
+ dst->data[0] = 0;
+ ret = smmu_sync_ste(smmu, sid);
+ if (ret)
+ goto out_unlock;
+ for (i = 1; i < STRTAB_STE_DWORDS; i++)
+ dst->data[i] = 0;
+
+ ret = smmu_sync_ste(smmu, sid);
+
+ smmu_free_cd(cd_table, pasid_bits);
+
+out_unlock:
+ kvm_iommu_unlock(iommu);
+ return ret;
+}
+
/* Shared with the kernel driver in EL1 */
struct kvm_iommu_ops smmu_ops = {
.init = smmu_init,
@@ -1060,4 +1133,5 @@ struct kvm_iommu_ops smmu_ops = {
.free_domain = smmu_free_domain,
.iotlb_sync = smmu_iotlb_sync,
.attach_dev = smmu_attach_dev,
+ .detach_dev = smmu_detach_dev,
};
--
2.47.0.338.g60cca15819-goog
Powered by blists - more mailing lists