From: Mostafa Saleh <smostafa@google.com>
To: linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org, kvmarm@lists.linux.dev,
iommu@lists.linux.dev
Cc: catalin.marinas@arm.com, will@kernel.org, maz@kernel.org,
oliver.upton@linux.dev, joey.gouly@arm.com,
suzuki.poulose@arm.com, yuzenghui@huawei.com, joro@8bytes.org,
jgg@ziepe.ca, mark.rutland@arm.com, qperret@google.com,
tabba@google.com, vdonnefort@google.com,
sebastianene@google.com, keirf@google.com,
Mostafa Saleh <smostafa@google.com>
Subject: [PATCH v7 16/24] iommu/arm-smmu-v3-kvm: Emulate CMDQ for host
Date: Wed, 15 Jul 2026 11:58:57 +0000 [thread overview]
Message-ID: <20260715115906.2664882-17-smostafa@google.com> (raw)
In-Reply-To: <20260715115906.2664882-1-smostafa@google.com>
Don’t allow access to the command queue from the host:
- ARM_SMMU_CMDQ_BASE: Only allowed to be written when CMDQ is disabled, we
use it to keep track of the host command queue base.
Reads return the saved value.
- ARM_SMMU_CMDQ_PROD: Writes trigger command queue emulation which sanitise
and filters the whole range. Reads returns the host copy.
- ARM_SMMU_CMDQ_CONS: Writes move the sw copy of the cons, but the host
can’t skip commands once submitted. Reads return the emulated value and
the error bits in the actual cons.
Signed-off-by: Mostafa Saleh <smostafa@google.com>
---
.../iommu/arm/arm-smmu-v3/pkvm/arm-smmu-v3.c | 133 +++++++++++++++++-
1 file changed, 129 insertions(+), 4 deletions(-)
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 8e798fd8fdaa..f62c9e8f2c59 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
@@ -105,7 +105,6 @@ static int smmu_unshare_pages(phys_addr_t addr, size_t size)
return 0;
}
-__maybe_unused
static bool smmu_cmdq_has_space(struct arm_smmu_queue *cmdq, u32 n)
{
struct arm_smmu_ll_queue *llq = &cmdq->llq;
@@ -330,6 +329,99 @@ static int smmu_init(void)
return ret;
}
+static bool smmu_filter_command(struct hyp_arm_smmu_v3_device *smmu, u64 *command)
+{
+ u64 type = FIELD_GET(CMDQ_0_OP, command[0]);
+
+ switch (type) {
+ case CMDQ_OP_CFGI_STE:
+ /* TBD: SHADOW_STE*/
+ break;
+ case CMDQ_OP_CFGI_ALL:
+ {
+ /*
+ * Linux doesn't use range STE invalidation, and only use this
+ * for CFGI_ALL, which is done on reset and not on an new STE
+ * being used.
+ * Although, this is not architectural we rely on the current Linux
+ * implementation.
+ */
+ if ((FIELD_GET(CMDQ_CFGI_1_RANGE, command[1]) != 31))
+ return true;
+ break;
+ }
+ case CMDQ_OP_TLBI_NH_ASID:
+ case CMDQ_OP_TLBI_NH_VA:
+ case 0x13: /* CMD_TLBI_NH_VAA: Not used by Linux */
+ {
+ /* Only allow VMID = 0 */
+ if (FIELD_GET(CMDQ_TLBI_0_VMID, command[0]) != 0)
+ return true;
+ break;
+ }
+ case CMDQ_OP_PREFETCH_CFG:
+ case CMDQ_OP_CFGI_CD:
+ case CMDQ_OP_CFGI_CD_ALL:
+ case CMDQ_OP_TLBI_NH_ALL:
+ case CMDQ_OP_TLBI_NSNH_ALL:
+ break;
+ case CMDQ_OP_CMD_SYNC:
+ if (FIELD_GET(CMDQ_SYNC_0_CS, command[0]) == CMDQ_SYNC_0_CS_IRQ) {
+ /* Allow it, but let the host timeout, as this should never happen. */
+ command[0] &= ~CMDQ_SYNC_0_CS;
+ command[0] |= FIELD_PREP(CMDQ_SYNC_0_CS, CMDQ_SYNC_0_CS_SEV);
+ command[1] &= ~CMDQ_SYNC_1_MSIADDR_MASK;
+ }
+ break;
+ default:
+ /* Deny unknown commands */
+ return true;
+ }
+
+ return false;
+}
+
+static int smmu_emulate_cmdq_insert(struct hyp_arm_smmu_v3_device *smmu)
+{
+ u64 *host_cmdq = hyp_phys_to_virt(smmu->cmdq_host.base_dma);
+ bool use_wfe = smmu->features & ARM_SMMU_FEAT_SEV, skip;
+ u64 cmd[CMDQ_ENT_DWORDS];
+ int idx, ret;
+ u32 space;
+
+ if (!is_cmdq_enabled(smmu))
+ return 0;
+
+ space = (1 << (smmu->cmdq_host.llq.max_n_shift)) - queue_space(&smmu->cmdq_host.llq);
+
+ /* Wait for the command queue to have some space. */
+ ret = smmu_wait(use_wfe, smmu_cmdq_has_space(&smmu->cmdq, space));
+ if (ret)
+ return ret;
+ hyp_spin_lock(&smmu->hw_lock);
+ while (space--) {
+ int i;
+
+ idx = Q_IDX(&smmu->cmdq_host.llq, smmu->cmdq_host.llq.cons);
+ queue_inc_cons(&smmu->cmdq_host.llq);
+
+ /* Copy the command to local buffer avoiding TOCTOU */
+ for (i = 0 ; i < CMDQ_ENT_DWORDS ; ++i)
+ cmd[i] = le64_to_cpu(READ_ONCE(host_cmdq[idx * CMDQ_ENT_DWORDS + i]));
+
+ skip = smmu_filter_command(smmu, cmd);
+ if (WARN_ON(skip))
+ continue;
+ smmu_add_cmd_raw(smmu, cmd);
+ }
+
+ writel(smmu->cmdq.llq.prod, smmu->cmdq.prod_reg);
+
+ ret = smmu_wait(use_wfe, smmu_cmdq_empty(&smmu->cmdq));
+ hyp_spin_unlock(&smmu->hw_lock);
+ return ret;
+}
+
static void smmu_emulate_cmdq_enable(struct hyp_arm_smmu_v3_device *smmu)
{
u32 shift = smmu->cmdq_host.q_base & Q_BASE_LOG2SIZE;
@@ -371,18 +463,51 @@ static bool smmu_dabt_device(struct hyp_arm_smmu_v3_device *smmu,
*/
mask = read_only & ~(IDR0_S2P | IDR0_VMID16 | IDR0_MSI | IDR0_HYP | IDR0_ATS);
break;
- /* Passthrough the register access for bisectiblity, handled later */
case ARM_SMMU_CMDQ_BASE:
+ /*
+ * Although allowed to use smaller size, we rely on the SMMUv3 driver
+ * using 64-bit store instruction for simplicity.
+ */
+ if (len != sizeof(u64))
+ break;
if (is_write) {
/* Not allowed by the architecture */
if (is_cmdq_enabled(smmu))
break;
smmu->cmdq_host.q_base = val;
+ goto out_ret;
+ } else {
+ val = smmu->cmdq_host.q_base;
+ goto out_update_regs;
}
- mask = read_write;
- break;
case ARM_SMMU_CMDQ_PROD:
+ if (len != sizeof(u32))
+ break;
+ if (is_write) {
+ smmu->cmdq_host.llq.prod = val;
+ WARN_ON(smmu_emulate_cmdq_insert(smmu));
+ goto out_ret;
+ } else {
+ val = smmu->cmdq_host.llq.prod;
+ goto out_update_regs;
+ }
case ARM_SMMU_CMDQ_CONS:
+ if (len != sizeof(u32))
+ break;
+ if (is_write) {
+ if (WARN_ON(is_cmdq_enabled(smmu)))
+ break;
+
+ smmu->cmdq_host.llq.cons = val;
+ goto out_ret;
+ } else {
+ /* Propagate errors back to the host.*/
+ u32 cons = readl_relaxed(smmu->base + ARM_SMMU_CMDQ_CONS);
+
+ val = smmu->cmdq_host.llq.cons | (CMDQ_CONS_ERR & cons);
+ goto out_update_regs;
+ }
+ /* Passthrough the register access for bisectiblity, handled later */
case ARM_SMMU_STRTAB_BASE:
case ARM_SMMU_STRTAB_BASE_CFG:
case ARM_SMMU_GBPA:
--
2.55.0.141.g00534a21ce-goog
next prev parent reply other threads:[~2026-07-15 11:59 UTC|newest]
Thread overview: 32+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-15 11:58 [PATCH v7 00/24] KVM: arm64: SMMUv3 driver for pKVM (trap and emulate) Mostafa Saleh
2026-07-15 11:58 ` [PATCH v7 01/24] KVM: arm64: Add a generic clock Mostafa Saleh
2026-07-15 13:48 ` Vincent Donnefort
2026-07-15 14:13 ` Mostafa Saleh
2026-07-15 14:34 ` Vincent Donnefort
2026-07-15 11:58 ` [PATCH v7 02/24] KVM: arm64: Donate MMIO to the hypervisor Mostafa Saleh
2026-07-15 17:26 ` Vincent Donnefort
2026-07-15 18:28 ` Mostafa Saleh
2026-07-15 11:58 ` [PATCH v7 03/24] iommu/arm-smmu-v3: Split code with hyp Mostafa Saleh
2026-07-15 11:58 ` [PATCH v7 04/24] iommu/arm-smmu-v3: Move TLB range invalidation into common code Mostafa Saleh
2026-07-15 11:58 ` [PATCH v7 05/24] iommu/arm-smmu-v3: Move IDR parsing to common functions Mostafa Saleh
2026-07-15 11:58 ` [PATCH v7 06/24] KVM: arm64: iommu: Introduce IOMMU driver infrastructure Mostafa Saleh
2026-07-15 11:58 ` [PATCH v7 07/24] KVM: arm64: iommu: Shadow host stage-2 page table Mostafa Saleh
2026-07-15 17:56 ` Vincent Donnefort
2026-07-15 18:43 ` Mostafa Saleh
2026-07-15 11:58 ` [PATCH v7 08/24] KVM: arm64: iommu: Add memory pool Mostafa Saleh
2026-07-15 11:58 ` [PATCH v7 09/24] KVM: arm64: iommu: Support DABT for IOMMU Mostafa Saleh
2026-07-15 11:58 ` [PATCH v7 10/24] iommu/arm-smmu-v3-kvm: Add SMMUv3 driver Mostafa Saleh
2026-07-15 11:58 ` [PATCH v7 11/24] iommu/arm-smmu-v3-kvm: Add the kernel driver Mostafa Saleh
2026-07-15 11:58 ` [PATCH v7 12/24] iommu/arm-smmu-v3-kvm: Probe SMMU HW Mostafa Saleh
2026-07-15 11:58 ` [PATCH v7 13/24] iommu/arm-smmu-v3-kvm: Add MMIO emulation Mostafa Saleh
2026-07-15 11:58 ` [PATCH v7 14/24] iommu/arm-smmu-v3-kvm: Shadow the command queue Mostafa Saleh
2026-07-15 11:58 ` [PATCH v7 15/24] iommu/arm-smmu-v3-kvm: Add CMDQ functions Mostafa Saleh
2026-07-15 11:58 ` Mostafa Saleh [this message]
2026-07-15 11:58 ` [PATCH v7 17/24] iommu/arm-smmu-v3-kvm: Shadow stream table Mostafa Saleh
2026-07-15 11:58 ` [PATCH v7 18/24] iommu/arm-smmu-v3-kvm: Shadow STEs Mostafa Saleh
2026-07-15 11:59 ` [PATCH v7 19/24] iommu/arm-smmu-v3-kvm: Share other queues Mostafa Saleh
2026-07-15 11:59 ` [PATCH v7 20/24] iommu/arm-smmu-v3-kvm: Emulate GBPA Mostafa Saleh
2026-07-15 11:59 ` [PATCH v7 21/24] iommu/io-pgtable-arm: Support io-pgtable-arm in the hypervisor Mostafa Saleh
2026-07-15 11:59 ` [PATCH v7 22/24] iommu/arm-smmu-v3-kvm: Shadow the CPU stage-2 page table Mostafa Saleh
2026-07-15 11:59 ` [PATCH v7 23/24] iommu/arm-smmu-v3-kvm: Enable nesting Mostafa Saleh
2026-07-15 11:59 ` [PATCH v7 24/24] KVM: arm64: Add documentation for pKVM DMA isolation Mostafa Saleh
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260715115906.2664882-17-smostafa@google.com \
--to=smostafa@google.com \
--cc=catalin.marinas@arm.com \
--cc=iommu@lists.linux.dev \
--cc=jgg@ziepe.ca \
--cc=joey.gouly@arm.com \
--cc=joro@8bytes.org \
--cc=keirf@google.com \
--cc=kvmarm@lists.linux.dev \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mark.rutland@arm.com \
--cc=maz@kernel.org \
--cc=oliver.upton@linux.dev \
--cc=qperret@google.com \
--cc=sebastianene@google.com \
--cc=suzuki.poulose@arm.com \
--cc=tabba@google.com \
--cc=vdonnefort@google.com \
--cc=will@kernel.org \
--cc=yuzenghui@huawei.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox