Skip to content

Commit

Permalink
hw/arm/smmuv3: Move reset to exit phase
Browse files Browse the repository at this point in the history
Currently the iommu may be reset before the devices
it protects. For example this happens with virtio-scsi-pci.
when system_reset is issued from qmp monitor: spurious
"virtio: zero sized buffers are not allowed" warnings can
be observed. This happens because outstanding DMA requests
are still happening while the SMMU gets reset.

This can also happen with VFIO devices. In that case
spurious DMA translation faults can be observed on host.

Make sure the SMMU is reset in the 'exit' phase after
all DMA capable devices have been reset during the 'enter'
or 'hold' phase.

Signed-off-by: Eric Auger <[email protected]>
Reviewed-by: Zhenzhong Duan <[email protected]>

Message-Id: <[email protected]>
Reviewed-by: Peter Xu <[email protected]>
Reviewed-by: Michael S. Tsirkin <[email protected]>
Signed-off-by: Michael S. Tsirkin <[email protected]>
  • Loading branch information
eauger authored and mstsirkin committed Feb 21, 2025
1 parent 2aaf48b commit e39e3f8
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 6 deletions.
9 changes: 7 additions & 2 deletions hw/arm/smmu-common.c
Original file line number Diff line number Diff line change
Expand Up @@ -924,7 +924,12 @@ static void smmu_base_realize(DeviceState *dev, Error **errp)
}
}

static void smmu_base_reset_hold(Object *obj, ResetType type)
/*
* Make sure the IOMMU is reset in 'exit' phase after
* all outstanding DMA requests have been quiesced during
* the 'enter' or 'hold' reset phases
*/
static void smmu_base_reset_exit(Object *obj, ResetType type)
{
SMMUState *s = ARM_SMMU(obj);

Expand All @@ -949,7 +954,7 @@ static void smmu_base_class_init(ObjectClass *klass, void *data)
device_class_set_props(dc, smmu_dev_properties);
device_class_set_parent_realize(dc, smmu_base_realize,
&sbc->parent_realize);
rc->phases.hold = smmu_base_reset_hold;
rc->phases.exit = smmu_base_reset_exit;
}

static const TypeInfo smmu_base_info = {
Expand Down
14 changes: 10 additions & 4 deletions hw/arm/smmuv3.c
Original file line number Diff line number Diff line change
Expand Up @@ -1870,13 +1870,19 @@ static void smmu_init_irq(SMMUv3State *s, SysBusDevice *dev)
}
}

static void smmu_reset_hold(Object *obj, ResetType type)
/*
* Make sure the IOMMU is reset in 'exit' phase after
* all outstanding DMA requests have been quiesced during
* the 'enter' or 'hold' reset phases
*/
static void smmu_reset_exit(Object *obj, ResetType type)
{
SMMUv3State *s = ARM_SMMUV3(obj);
SMMUv3Class *c = ARM_SMMUV3_GET_CLASS(s);

if (c->parent_phases.hold) {
c->parent_phases.hold(obj, type);
trace_smmu_reset_exit();
if (c->parent_phases.exit) {
c->parent_phases.exit(obj, type);
}

smmuv3_init_regs(s);
Expand Down Expand Up @@ -1999,7 +2005,7 @@ static void smmuv3_class_init(ObjectClass *klass, void *data)
SMMUv3Class *c = ARM_SMMUV3_CLASS(klass);

dc->vmsd = &vmstate_smmuv3;
resettable_class_set_parent_phases(rc, NULL, smmu_reset_hold, NULL,
resettable_class_set_parent_phases(rc, NULL, NULL, smmu_reset_exit,
&c->parent_phases);
device_class_set_parent_realize(dc, smmu_realize,
&c->parent_realize);
Expand Down
1 change: 1 addition & 0 deletions hw/arm/trace-events
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ smmuv3_config_cache_inv(uint32_t sid) "Config cache INV for sid=0x%x"
smmuv3_notify_flag_add(const char *iommu) "ADD SMMUNotifier node for iommu mr=%s"
smmuv3_notify_flag_del(const char *iommu) "DEL SMMUNotifier node for iommu mr=%s"
smmuv3_inv_notifiers_iova(const char *name, int asid, int vmid, uint64_t iova, uint8_t tg, uint64_t num_pages, int stage) "iommu mr=%s asid=%d vmid=%d iova=0x%"PRIx64" tg=%d num_pages=0x%"PRIx64" stage=%d"
smmu_reset_exit(void) ""

# strongarm.c
strongarm_uart_update_parameters(const char *label, int speed, char parity, int data_bits, int stop_bits) "%s speed=%d parity=%c data=%d stop=%d"
Expand Down

0 comments on commit e39e3f8

Please sign in to comment.