[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [PATCH v3 08/23] xen/arm: vsmmuv3: Add support for registers emulation
- To: Luca Fancellu <Luca.Fancellu@xxxxxxx>
- From: Milan Djokic <milan_djokic@xxxxxxxx>
- Date: Mon, 18 May 2026 02:17:07 +0200
- Arc-authentication-results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=epam.com; dmarc=pass action=none header.from=epam.com; dkim=pass header.d=epam.com; arc=none
- Arc-message-signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=X9Hztv43pW+b9Svw/ou9qn/Zo1JDXaUfuZfdgYW6Db4=; b=WIK3RjXGpryea05K3UHRteYnPiUK3OkqlyPqpac1BzwcO6d4ZcpzPVsWaWEJCt7X1gJfOyjfO/QcE7MHoQZuqf6Eq1c8NrE9CU4+qm79HMj12WfOjgGmPDSfPeQV4pXi+4sjzRiI2EpfUd5bRb7tFIDetmXK40ySPjP2XinKxbdT3wHQ6FNuopecltVnKVc9eCuj0W3ZoYGuk+ETFx41DYVzSdkJUOD0oPK7xBAV3GeHdF5e7SNtPzgpE5g7rRjni5wwnV63fy/xuEh/eDMJEwhxfxTpna+sZsxgP4CtN9bJeVU4Z4/ktYHbUgZ/p4czstzK4BUPMWQ83cY+8rQttA==
- Arc-seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=UsLen5IY62MU9o4iJ1MUkX6nT9/CUSq3qpb6xoAXD+X+l+BZDpxC/94EjXoCd706OXNy/oNo4rmAvn2wAabPGbNru6yIO3UIeBG5NZqRQjDVuSwJsqoSzfG9js481W9YhL6vxWdn+/P1OiIhWLvURzkYkM+KNKZMRQTx6rracCgXH+Mt5WNHNFyXge42bw6Qg8B9OlduqQVC5u+eWM6y/NlS7qAtmdZGttS0QCmniX1GizZPw4tyFZdKwyKbXQRMDvCI1bzaVsTt5UQumIV58S3HCfI+6q8ruxZMfZZ1xAyM5u2EcpEdMHOiS8u6ff3AVLLCnujETli0Z9aumP+h0Q==
- Authentication-results: eu.smtp.expurgate.cloud; dkim=pass header.s=selector1 header.d=epam.com header.i="@epam.com" header.h="From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck"
- Authentication-results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=epam.com;
- Cc: "xen-devel@xxxxxxxxxxxxxxxxxxxx" <xen-devel@xxxxxxxxxxxxxxxxxxxx>, Rahul Singh <Rahul.Singh@xxxxxxx>, Stefano Stabellini <sstabellini@xxxxxxxxxx>, Julien Grall <julien@xxxxxxx>, Bertrand Marquis <Bertrand.Marquis@xxxxxxx>, Michal Orzel <michal.orzel@xxxxxxx>, Volodymyr Babchuk <Volodymyr_Babchuk@xxxxxxxx>
- Delivery-date: Mon, 18 May 2026 00:17:36 +0000
- List-id: Xen developer discussion <xen-devel.lists.xenproject.org>
Hi Luca,
On 4/10/26 17:27, Luca Fancellu wrote:
Hi Milan,
diff --git a/xen/drivers/passthrough/arm/vsmmu-v3.c
b/xen/drivers/passthrough/arm/vsmmu-v3.c
index e36f200ba5..3ae1e62a50 100644
--- a/xen/drivers/passthrough/arm/vsmmu-v3.c
+++ b/xen/drivers/passthrough/arm/vsmmu-v3.c
[...]
static int vsmmuv3_mmio_write(struct vcpu *v, mmio_info_t *info,
register_t r, void *priv)
{
+ struct virt_smmu *smmu = priv;
+ uint64_t reg;
+ uint32_t reg32;
+
+ switch ( info->gpa & 0xffff )
+ {
+ case VREG32(ARM_SMMU_CR0):
+ reg32 = smmu->cr[0];
+ vreg_reg32_update(®32, r, info);
+ smmu->cr[0] = reg32;
+ smmu->cr0ack = reg32 & ~CR0_RESERVED;
+ break;
+
+ case VREG32(ARM_SMMU_CR1):
+ reg32 = smmu->cr[1];
+ vreg_reg32_update(®32, r, info);
+ smmu->cr[1] = reg32;
+ break;
+
+ case VREG32(ARM_SMMU_CR2):
+ reg32 = smmu->cr[2];
+ vreg_reg32_update(®32, r, info);
+ smmu->cr[2] = reg32;
+ break;
+
+ case VREG64(ARM_SMMU_STRTAB_BASE):
+ reg = smmu->strtab_base;
+ vreg_reg64_update(®, r, info);
+ smmu->strtab_base = reg;
+ break;
+
+ case VREG32(ARM_SMMU_STRTAB_BASE_CFG):
+ reg32 = smmu->strtab_base_cfg;
+ vreg_reg32_update(®32, r, info);
+ smmu->strtab_base_cfg = reg32;
+
+ smmu->sid_split = FIELD_GET(STRTAB_BASE_CFG_SPLIT, reg32);
+ smmu->features |= STRTAB_BASE_CFG_FMT_2LVL;
+ break;
+
+ case VREG32(ARM_SMMU_CMDQ_BASE):
I think this needs to be VREG64
+ reg = smmu->cmdq.q_base;
+ vreg_reg64_update(®, r, info);
+ smmu->cmdq.q_base = reg;
+ smmu->cmdq.max_n_shift = FIELD_GET(Q_BASE_LOG2SIZE, smmu->cmdq.q_base);
+ if ( smmu->cmdq.max_n_shift > SMMU_CMDQS )
+ smmu->cmdq.max_n_shift = SMMU_CMDQS;
+ break;
+
+ case VREG32(ARM_SMMU_CMDQ_PROD):
+ reg32 = smmu->cmdq.prod;
+ vreg_reg32_update(®32, r, info);
+ smmu->cmdq.prod = reg32;
+ break;
+
+ case VREG32(ARM_SMMU_CMDQ_CONS):
+ reg32 = smmu->cmdq.cons;
+ vreg_reg32_update(®32, r, info);
+ smmu->cmdq.cons = reg32;
+ break;
+
+ case VREG32(ARM_SMMU_EVTQ_BASE):
And also this one VREG64
+ reg = smmu->evtq.q_base;
+ vreg_reg64_update(®, r, info);
+ smmu->evtq.q_base = reg;
+ smmu->evtq.max_n_shift = FIELD_GET(Q_BASE_LOG2SIZE, smmu->evtq.q_base);
+ if ( smmu->cmdq.max_n_shift > SMMU_EVTQS )
+ smmu->cmdq.max_n_shift = SMMU_EVTQS;
This seems a typo, I think here we want to modify the evtq, not the cmdq?
So in case both condition and assignment needs to change.
+ break;
+
+ case VREG32(ARM_SMMU_EVTQ_PROD):
+ reg32 = smmu->evtq.prod;
+ vreg_reg32_update(®32, r, info);
+ smmu->evtq.prod = reg32;
+ break;
+
+ case VREG32(ARM_SMMU_EVTQ_CONS):
+ reg32 = smmu->evtq.cons;
+ vreg_reg32_update(®32, r, info);
+ smmu->evtq.cons = reg32;
+ break;
+
+ case VREG32(ARM_SMMU_IRQ_CTRL):
+ reg32 = smmu->irq_ctrl;
+ vreg_reg32_update(®32, r, info);
+ smmu->irq_ctrl = reg32;
+ break;
+
+ case VREG64(ARM_SMMU_GERROR_IRQ_CFG0):
+ reg = smmu->gerror_irq_cfg0;
+ vreg_reg64_update(®, r, info);
+ smmu->gerror_irq_cfg0 = reg;
+ break;
+
+ case VREG64(ARM_SMMU_EVTQ_IRQ_CFG0):
+ reg = smmu->evtq_irq_cfg0;
+ vreg_reg64_update(®, r, info);
+ smmu->evtq_irq_cfg0 = reg;
+ break;
+
+ case VREG32(ARM_SMMU_GERRORN):
+ reg = smmu->gerrorn;
+ vreg_reg64_update(®, r, info);
this should be vreg_reg32_update
+ smmu->gerrorn = reg;
+ break;
+
+ default:
+ printk(XENLOG_G_ERR
+ "%pv: vSMMUv3: unhandled write r%d offset %"PRIpaddr"\n",
+ v, info->dabt.reg, (unsigned long)info->gpa & 0xffff);
+ return IO_ABORT;
+ }
+
return IO_HANDLED;
}
static int vsmmuv3_mmio_read(struct vcpu *v, mmio_info_t *info,
register_t *r, void *priv)
{
+ struct virt_smmu *smmu = priv;
+ uint64_t reg;
+
+ switch ( info->gpa & 0xffff )
+ {
+ case VREG32(ARM_SMMU_IDR0):
+ reg = FIELD_PREP(IDR0_S1P, 1) | FIELD_PREP(IDR0_TTF, 2) |
+ FIELD_PREP(IDR0_COHACC, 0) | FIELD_PREP(IDR0_ASID16, 1) |
+ FIELD_PREP(IDR0_TTENDIAN, 0) | FIELD_PREP(IDR0_STALL_MODEL, 1) |
+ FIELD_PREP(IDR0_ST_LVL, 1) | FIELD_PREP(IDR0_TERM_MODEL, 1);
+ *r = vreg_reg32_extract(reg, info);
+ break;
+
+ case VREG32(ARM_SMMU_IDR1):
+ reg = FIELD_PREP(IDR1_SIDSIZE, SMMU_IDR1_SIDSIZE) |
+ FIELD_PREP(IDR1_CMDQS, SMMU_CMDQS) |
+ FIELD_PREP(IDR1_EVTQS, SMMU_EVTQS);
+ *r = vreg_reg32_extract(reg, info);
+ break;
+
+ case VREG32(ARM_SMMU_IDR2):
+ goto read_reserved;
+
+ case VREG32(ARM_SMMU_IDR3):
+ reg = FIELD_PREP(IDR3_RIL, 0);
+ *r = vreg_reg32_extract(reg, info);
+ break;
+
+ case VREG32(ARM_SMMU_IDR4):
+ goto read_impl_defined;
+
+ case VREG32(ARM_SMMU_IDR5):
+ reg = FIELD_PREP(IDR5_GRAN4K, 1) | FIELD_PREP(IDR5_GRAN16K, 1) |
+ FIELD_PREP(IDR5_GRAN64K, 1) | FIELD_PREP(IDR5_OAS,
IDR5_OAS_48_BIT);
+ *r = vreg_reg32_extract(reg, info);
+ break;
+
+ case VREG32(ARM_SMMU_IIDR):
+ *r = vreg_reg32_extract(ARM_SMMU_IIDR_VAL, info);
+ break;
+
+ case VREG32(ARM_SMMU_CR0):
+ *r = vreg_reg32_extract(smmu->cr[0], info);
+ break;
+
+ case VREG32(ARM_SMMU_CR0ACK):
+ *r = vreg_reg32_extract(smmu->cr0ack, info);
+ break;
+
+ case VREG32(ARM_SMMU_CR1):
+ *r = vreg_reg32_extract(smmu->cr[1], info);
+ break;
+
+ case VREG32(ARM_SMMU_CR2):
+ *r = vreg_reg32_extract(smmu->cr[2], info);
+ break;
+
+ case VREG32(ARM_SMMU_STRTAB_BASE):
this needs to be VREG64 I think
+ *r = vreg_reg64_extract(smmu->strtab_base, info);
+ break;
+
+ case VREG32(ARM_SMMU_STRTAB_BASE_CFG):
+ *r = vreg_reg32_extract(smmu->strtab_base_cfg, info);
+ break;
+
+ case VREG32(ARM_SMMU_CMDQ_BASE):
VREG64
+ *r = vreg_reg64_extract(smmu->cmdq.q_base, info);
+ break;
+
+ case VREG32(ARM_SMMU_CMDQ_PROD):
+ *r = vreg_reg32_extract(smmu->cmdq.prod, info);
+ break;
+
+ case VREG32(ARM_SMMU_CMDQ_CONS):
+ *r = vreg_reg32_extract(smmu->cmdq.cons, info);
+ break;
+
+ case VREG32(ARM_SMMU_EVTQ_BASE):
VREG64
+ *r = vreg_reg64_extract(smmu->evtq.q_base, info);
+ break;
+
+ case VREG32(ARM_SMMU_EVTQ_PROD):
+ *r = vreg_reg32_extract(smmu->evtq.prod, info);
+ break;
+
+ case VREG32(ARM_SMMU_EVTQ_CONS):
+ *r = vreg_reg32_extract(smmu->evtq.cons, info);
+ break;
+
+ case VREG32(ARM_SMMU_IRQ_CTRL):
+ case VREG32(ARM_SMMU_IRQ_CTRLACK):
+ *r = vreg_reg32_extract(smmu->irq_ctrl, info);
+ break;
+
+ case VREG64(ARM_SMMU_GERROR_IRQ_CFG0):
+ *r = vreg_reg64_extract(smmu->gerror_irq_cfg0, info);
+ break;
+
+ case VREG64(ARM_SMMU_EVTQ_IRQ_CFG0):
+ *r = vreg_reg64_extract(smmu->evtq_irq_cfg0, info);
+ break;
+
+ case VREG32(ARM_SMMU_GERROR):
+ *r = vreg_reg64_extract(smmu->gerror, info);
vreg_reg32_extract
+ break;
+
+ case VREG32(ARM_SMMU_GERRORN):
+ *r = vreg_reg64_extract(smmu->gerrorn, info);
vreg_reg32_extract
Yes, these are all mismatches. I'll fix them in the next revision.
+ break;
+
+ default:
+ printk(XENLOG_G_ERR
+ "%pv: vSMMUv3: unhandled read r%d offset %"PRIpaddr"\n",
+ v, info->dabt.reg, (unsigned long)info->gpa & 0xffff);
+ return IO_ABORT;
+ }
+
+ return IO_HANDLED;
+
+ read_impl_defined:
+ printk(XENLOG_G_DEBUG
+ "%pv: vSMMUv3: RAZ on implementation defined register offset
%"PRIpaddr"\n",
+ v, info->gpa & 0xffff);
+ *r = 0;
+ return IO_HANDLED;
+
+ read_reserved:
+ printk(XENLOG_G_DEBUG
+ "%pv: vSMMUv3: RAZ on reserved register offset %"PRIpaddr"\n",
+ v, info->gpa & 0xffff);
+ *r = 0;
return IO_HANDLED;
}
Cheers,
Luca
BR,
Milan
|