|
[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
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
> + 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
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |