[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20250819215156.2494305-22-smostafa@google.com>
Date: Tue, 19 Aug 2025 21:51:49 +0000
From: Mostafa Saleh <smostafa@...gle.com>
To: linux-kernel@...r.kernel.org, kvmarm@...ts.linux.dev,
linux-arm-kernel@...ts.infradead.org, iommu@...ts.linux.dev
Cc: maz@...nel.org, oliver.upton@...ux.dev, joey.gouly@....com,
suzuki.poulose@....com, yuzenghui@...wei.com, catalin.marinas@....com,
will@...nel.org, robin.murphy@....com, jean-philippe@...aro.org,
qperret@...gle.com, tabba@...gle.com, jgg@...pe.ca, mark.rutland@....com,
praan@...gle.com, Mostafa Saleh <smostafa@...gle.com>
Subject: [PATCH v4 21/28] iommu/arm-smmu-v3-kvm: Add CMDQ functions
Add functions to access the command queue, there are 2 main usage:
- Hypervisor's own commands, as TLB invalidation, would use functions
as smmu_send_cmd(), which creates and sends a command.
- Add host commands to the shadow command queue, after being filtered,
these will be added with smmu_add_cmd_raw.
Signed-off-by: Mostafa Saleh <smostafa@...gle.com>
---
.../iommu/arm/arm-smmu-v3/pkvm/arm-smmu-v3.c | 98 +++++++++++++++++++
1 file changed, 98 insertions(+)
diff --git a/drivers/iommu/arm/arm-smmu-v3/pkvm/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/pkvm/arm-smmu-v3.c
index d3ab4b814be4..554229e466f3 100644
--- a/drivers/iommu/arm/arm-smmu-v3/pkvm/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/pkvm/arm-smmu-v3.c
@@ -20,6 +20,33 @@ struct hyp_arm_smmu_v3_device *kvm_hyp_arm_smmu_v3_smmus;
(smmu) != &kvm_hyp_arm_smmu_v3_smmus[kvm_hyp_arm_smmu_v3_count]; \
(smmu)++)
+/*
+ * Wait until @cond is true.
+ * Return 0 on success, or -ETIMEDOUT
+ */
+#define smmu_wait(_cond) \
+({ \
+ int __ret = 0; \
+ u64 delay = pkvm_time_get() + ARM_SMMU_POLL_TIMEOUT_US; \
+ \
+ while (!(_cond)) { \
+ if (pkvm_time_get() >= delay) { \
+ __ret = -ETIMEDOUT; \
+ break; \
+ } \
+ } \
+ __ret; \
+})
+
+#define smmu_wait_event(_smmu, _cond) \
+({ \
+ if ((_smmu)->features & ARM_SMMU_FEAT_SEV) { \
+ while (!(_cond)) \
+ wfe(); \
+ } \
+ smmu_wait(_cond); \
+})
+
/* Transfer ownership of memory */
static int smmu_take_pages(u64 phys, size_t size)
{
@@ -62,6 +89,77 @@ static int smmu_unshare_pages(phys_addr_t addr, size_t size)
return 0;
}
+static bool smmu_cmdq_full(struct arm_smmu_queue *cmdq)
+{
+ struct arm_smmu_ll_queue *llq = &cmdq->llq;
+
+ WRITE_ONCE(llq->cons, readl_relaxed(cmdq->cons_reg));
+ return queue_full(llq);
+}
+
+static bool smmu_cmdq_empty(struct arm_smmu_queue *cmdq)
+{
+ struct arm_smmu_ll_queue *llq = &cmdq->llq;
+
+ WRITE_ONCE(llq->cons, readl_relaxed(cmdq->cons_reg));
+ return queue_empty(llq);
+}
+
+static void smmu_add_cmd_raw(struct hyp_arm_smmu_v3_device *smmu,
+ u64 *cmd)
+{
+ struct arm_smmu_queue *q = &smmu->cmdq;
+ struct arm_smmu_ll_queue *llq = &q->llq;
+
+ queue_write(Q_ENT(q, llq->prod), cmd, CMDQ_ENT_DWORDS);
+ llq->prod = queue_inc_prod_n(llq, 1);
+ writel_relaxed(llq->prod, q->prod_reg);
+}
+
+static int smmu_add_cmd(struct hyp_arm_smmu_v3_device *smmu,
+ struct arm_smmu_cmdq_ent *ent)
+{
+ int ret;
+ u64 cmd[CMDQ_ENT_DWORDS];
+
+ ret = smmu_wait_event(smmu, !smmu_cmdq_full(&smmu->cmdq));
+ if (ret)
+ return ret;
+
+ ret = arm_smmu_cmdq_build_cmd(cmd, ent);
+ if (ret)
+ return ret;
+
+ smmu_add_cmd_raw(smmu, cmd);
+ return 0;
+}
+
+static int smmu_sync_cmd(struct hyp_arm_smmu_v3_device *smmu)
+{
+ int ret;
+ struct arm_smmu_cmdq_ent cmd = {
+ .opcode = CMDQ_OP_CMD_SYNC,
+ };
+
+ ret = smmu_add_cmd(smmu, &cmd);
+ if (ret)
+ return ret;
+
+ return smmu_wait_event(smmu, smmu_cmdq_empty(&smmu->cmdq));
+}
+
+__maybe_unused
+static int smmu_send_cmd(struct hyp_arm_smmu_v3_device *smmu,
+ struct arm_smmu_cmdq_ent *cmd)
+{
+ int ret = smmu_add_cmd(smmu, cmd);
+
+ if (ret)
+ return ret;
+
+ return smmu_sync_cmd(smmu);
+}
+
/* Put the device in a state that can be probed by the host driver. */
static void smmu_deinit_device(struct hyp_arm_smmu_v3_device *smmu)
{
--
2.51.0.rc1.167.g924127e9c0-goog
Powered by blists - more mailing lists