diff mbox series

[v2] virtio: Add corresponding memory_listener_unregister to unrealize

Message ID 20210125192505.390554-1-eperezma@redhat.com
State New
Headers show
Series [v2] virtio: Add corresponding memory_listener_unregister to unrealize | expand

Commit Message

Eugenio Perez Martin Jan. 25, 2021, 7:25 p.m. UTC
Address space is destroyed without proper removal of its listeners with
current code. They are expected to be removed in
virtio_device_instance_finalize [1], but qemu calls it through
object_deinit, after address_space_destroy call through
device_set_realized [2].

Move it to virtio_device_unrealize, called before device_set_realized
[3] and making it symmetric with memory_listener_register in
virtio_device_realize.

v2: Delete no-op call of virtio_device_instance_finalize.
    Add backtraces.

[1]

 #0  virtio_device_instance_finalize (obj=0x555557de5120)
     at /home/qemu/include/hw/virtio/virtio.h:71
 #1  0x0000555555b703c9 in object_deinit (type=0x555556639860,
      obj=<optimized out>) at ../qom/object.c:671
 #2  object_finalize (data=0x555557de5120) at ../qom/object.c:685
 #3  object_unref (objptr=0x555557de5120) at ../qom/object.c:1184
 #4  0x0000555555b4de9d in bus_free_bus_child (kid=0x555557df0660)
     at ../hw/core/qdev.c:55
 #5  0x0000555555c65003 in call_rcu_thread (opaque=opaque@entry=0x0)
     at ../util/rcu.c:281

Queued by:

 #0  bus_remove_child (bus=0x555557de5098,
     child=child@entry=0x555557de5120) at ../hw/core/qdev.c:60
 #1  0x0000555555b4ee31 in device_unparent (obj=<optimized out>)
     at ../hw/core/qdev.c:984
 #2  0x0000555555b70465 in object_finalize_child_property (
     obj=<optimized out>, name=<optimized out>, opaque=0x555557de5120)
     at ../qom/object.c:1725
 #3  0x0000555555b6fa17 in object_property_del_child (
     child=0x555557de5120, obj=0x555557ddcf90) at ../qom/object.c:645
 #4  object_unparent (obj=0x555557de5120) at ../qom/object.c:664
 #5  0x0000555555b4c071 in bus_unparent (obj=<optimized out>)
     at ../hw/core/bus.c:147
 #6  0x0000555555b70465 in object_finalize_child_property (
     obj=<optimized out>, name=<optimized out>, opaque=0x555557de5098)
     at ../qom/object.c:1725
 #7  0x0000555555b6fa17 in object_property_del_child (
     child=0x555557de5098, obj=0x555557ddcf90) at ../qom/object.c:645
 #8  object_unparent (obj=0x555557de5098) at ../qom/object.c:664
 #9  0x0000555555b4ee19 in device_unparent (obj=<optimized out>)
     at ../hw/core/qdev.c:981
 #10 0x0000555555b70465 in object_finalize_child_property (
     obj=<optimized out>, name=<optimized out>, opaque=0x555557ddcf90)
     at ../qom/object.c:1725
 #11 0x0000555555b6fa17 in object_property_del_child (
     child=0x555557ddcf90, obj=0x55555685da10) at ../qom/object.c:645
 #12 object_unparent (obj=0x555557ddcf90) at ../qom/object.c:664
 #13 0x00005555558dc331 in pci_for_each_device_under_bus (
     opaque=<optimized out>, fn=<optimized out>, bus=<optimized out>)
     at ../hw/pci/pci.c:1654

[2]

Optimizer omits pci_qdev_unrealize, called by device_set_realized, and
do_pci_unregister_device, called by pci_qdev_unrealize and caller of
address_space_destroy.

 #0  address_space_destroy (as=0x555557ddd1b8)
     at ../softmmu/memory.c:2840
 #1  0x0000555555b4fc53 in device_set_realized (obj=0x555557ddcf90,
      value=<optimized out>, errp=0x7fffeea8f1e0)
     at ../hw/core/qdev.c:850
 #2  0x0000555555b6eaa6 in property_set_bool (obj=0x555557ddcf90,
      v=<optimized out>, name=<optimized out>, opaque=0x555556650ba0,
     errp=0x7fffeea8f1e0) at ../qom/object.c:2255
 #3  0x0000555555b70e07 in object_property_set (
      obj=obj@entry=0x555557ddcf90,
      name=name@entry=0x555555db99df "realized",
      v=v@entry=0x7fffe46b7500,
      errp=errp@entry=0x5555565bbf38 <error_abort>)
     at ../qom/object.c:1400
 #4  0x0000555555b73c5f in object_property_set_qobject (
      obj=obj@entry=0x555557ddcf90,
      name=name@entry=0x555555db99df "realized",
      value=value@entry=0x7fffe44f6180,
      errp=errp@entry=0x5555565bbf38 <error_abort>)
     at ../qom/qom-qobject.c:28
 #5  0x0000555555b71044 in object_property_set_bool (
      obj=0x555557ddcf90, name=0x555555db99df "realized",
      value=<optimized out>, errp=0x5555565bbf38 <error_abort>)
     at ../qom/object.c:1470
 #6  0x0000555555921cb7 in pcie_unplug_device (bus=<optimized out>,
      dev=0x555557ddcf90,
      opaque=<optimized out>) at /home/qemu/include/hw/qdev-core.h:17
 #7  0x00005555558dc331 in pci_for_each_device_under_bus (
      opaque=<optimized out>, fn=<optimized out>,
      bus=<optimized out>) at ../hw/pci/pci.c:1654

[3]

 #0  virtio_device_unrealize (dev=0x555557de5120)
     at ../hw/virtio/virtio.c:3680
 #1  0x0000555555b4fc63 in device_set_realized (obj=0x555557de5120,
     value=<optimized out>, errp=0x7fffee28df90)
     at ../hw/core/qdev.c:850
 #2  0x0000555555b6eab6 in property_set_bool (obj=0x555557de5120,
     v=<optimized out>, name=<optimized out>, opaque=0x555556650ba0,
     errp=0x7fffee28df90) at ../qom/object.c:2255
 #3  0x0000555555b70e17 in object_property_set (
     obj=obj@entry=0x555557de5120,
     name=name@entry=0x555555db99ff "realized",
     v=v@entry=0x7ffdd8035040,
     errp=errp@entry=0x5555565bbf38 <error_abort>)
     at ../qom/object.c:1400
 #4  0x0000555555b73c6f in object_property_set_qobject (
     obj=obj@entry=0x555557de5120,
     name=name@entry=0x555555db99ff "realized",
     value=value@entry=0x7ffdd8035020,
     errp=errp@entry=0x5555565bbf38 <error_abort>)
     at ../qom/qom-qobject.c:28
 #5  0x0000555555b71054 in object_property_set_bool (
     obj=0x555557de5120, name=name@entry=0x555555db99ff "realized",
     value=value@entry=false, errp=0x5555565bbf38 <error_abort>)
     at ../qom/object.c:1470
 #6  0x0000555555b4edc5 in qdev_unrealize (dev=<optimized out>)
     at ../hw/core/qdev.c:403
 #7  0x0000555555b4c2a9 in bus_set_realized (obj=<optimized out>,
     value=<optimized out>, errp=<optimized out>)
     at ../hw/core/bus.c:204
 #8  0x0000555555b6eab6 in property_set_bool (obj=0x555557de5098,
     v=<optimized out>, name=<optimized out>, opaque=0x555557df04c0,
     errp=0x7fffee28e0a0) at ../qom/object.c:2255
 #9  0x0000555555b70e17 in object_property_set (
     obj=obj@entry=0x555557de5098,
     name=name@entry=0x555555db99ff "realized",
     v=v@entry=0x7ffdd8034f50,
     errp=errp@entry=0x5555565bbf38 <error_abort>)
     at ../qom/object.c:1400
 #10 0x0000555555b73c6f in object_property_set_qobject (
     obj=obj@entry=0x555557de5098,
     name=name@entry=0x555555db99ff "realized",
     value=value@entry=0x7ffdd8020630,
     errp=errp@entry=0x5555565bbf38 <error_abort>)
     at ../qom/qom-qobject.c:28
 #11 0x0000555555b71054 in object_property_set_bool (
     obj=obj@entry=0x555557de5098,
     name=name@entry=0x555555db99ff "realized",
     value=value@entry=false, errp=0x5555565bbf38 <error_abort>)
     at ../qom/object.c:1470
 #12 0x0000555555b4c725 in qbus_unrealize (
     bus=bus@entry=0x555557de5098) at ../hw/core/bus.c:178
 #13 0x0000555555b4fc00 in device_set_realized (obj=0x555557ddcf90,
     value=<optimized out>, errp=0x7fffee28e1e0)
     at ../hw/core/qdev.c:844
 #14 0x0000555555b6eab6 in property_set_bool (obj=0x555557ddcf90,
     v=<optimized out>, name=<optimized out>, opaque=0x555556650ba0,
     errp=0x7fffee28e1e0) at ../qom/object.c:2255
 #15 0x0000555555b70e17 in object_property_set (
     obj=obj@entry=0x555557ddcf90,
     name=name@entry=0x555555db99ff "realized",
     v=v@entry=0x7ffdd8020560,
     errp=errp@entry=0x5555565bbf38 <error_abort>)
     at ../qom/object.c:1400
 #16 0x0000555555b73c6f in object_property_set_qobject (
     obj=obj@entry=0x555557ddcf90,
     name=name@entry=0x555555db99ff "realized",
     value=value@entry=0x7ffdd8020540,
     errp=errp@entry=0x5555565bbf38 <error_abort>)
     at ../qom/qom-qobject.c:28
 #17 0x0000555555b71054 in object_property_set_bool (
     obj=0x555557ddcf90, name=0x555555db99ff "realized",
     value=<optimized out>, errp=0x5555565bbf38 <error_abort>)
     at ../qom/object.c:1470
 #18 0x0000555555921cb7 in pcie_unplug_device (bus=<optimized out>,
     dev=0x555557ddcf90, opaque=<optimized out>)
     at /home/qemu/include/hw/qdev-core.h:17
 #19 0x00005555558dc331 in pci_for_each_device_under_bus (
     opaque=<optimized out>, fn=<optimized out>, bus=<optimized out>)
     at ../hw/pci/pci.c:1654

Fixes: c611c76417f ("virtio: add MemoryListener to cache ring translations")
Buglink: https://bugs.launchpad.net/qemu/+bug/1912846
Signed-off-by: Eugenio Pérez <eperezma@redhat.com>
---
 hw/virtio/virtio.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

Comments

Peter Xu Jan. 26, 2021, 3:40 p.m. UTC | #1
On Mon, Jan 25, 2021 at 08:25:05PM +0100, Eugenio Pérez wrote:
> Address space is destroyed without proper removal of its listeners with
> current code. They are expected to be removed in
> virtio_device_instance_finalize [1], but qemu calls it through
> object_deinit, after address_space_destroy call through
> device_set_realized [2].
> 
> Move it to virtio_device_unrealize, called before device_set_realized
> [3] and making it symmetric with memory_listener_register in
> virtio_device_realize.
> 
> v2: Delete no-op call of virtio_device_instance_finalize.
>     Add backtraces.

This can be dropped from commit.

> 
> [1]
> 
>  #0  virtio_device_instance_finalize (obj=0x555557de5120)
>      at /home/qemu/include/hw/virtio/virtio.h:71
>  #1  0x0000555555b703c9 in object_deinit (type=0x555556639860,
>       obj=<optimized out>) at ../qom/object.c:671
>  #2  object_finalize (data=0x555557de5120) at ../qom/object.c:685
>  #3  object_unref (objptr=0x555557de5120) at ../qom/object.c:1184
>  #4  0x0000555555b4de9d in bus_free_bus_child (kid=0x555557df0660)
>      at ../hw/core/qdev.c:55
>  #5  0x0000555555c65003 in call_rcu_thread (opaque=opaque@entry=0x0)
>      at ../util/rcu.c:281
> 
> Queued by:
> 
>  #0  bus_remove_child (bus=0x555557de5098,
>      child=child@entry=0x555557de5120) at ../hw/core/qdev.c:60
>  #1  0x0000555555b4ee31 in device_unparent (obj=<optimized out>)
>      at ../hw/core/qdev.c:984
>  #2  0x0000555555b70465 in object_finalize_child_property (
>      obj=<optimized out>, name=<optimized out>, opaque=0x555557de5120)
>      at ../qom/object.c:1725
>  #3  0x0000555555b6fa17 in object_property_del_child (
>      child=0x555557de5120, obj=0x555557ddcf90) at ../qom/object.c:645
>  #4  object_unparent (obj=0x555557de5120) at ../qom/object.c:664
>  #5  0x0000555555b4c071 in bus_unparent (obj=<optimized out>)
>      at ../hw/core/bus.c:147
>  #6  0x0000555555b70465 in object_finalize_child_property (
>      obj=<optimized out>, name=<optimized out>, opaque=0x555557de5098)
>      at ../qom/object.c:1725
>  #7  0x0000555555b6fa17 in object_property_del_child (
>      child=0x555557de5098, obj=0x555557ddcf90) at ../qom/object.c:645
>  #8  object_unparent (obj=0x555557de5098) at ../qom/object.c:664
>  #9  0x0000555555b4ee19 in device_unparent (obj=<optimized out>)
>      at ../hw/core/qdev.c:981
>  #10 0x0000555555b70465 in object_finalize_child_property (
>      obj=<optimized out>, name=<optimized out>, opaque=0x555557ddcf90)
>      at ../qom/object.c:1725
>  #11 0x0000555555b6fa17 in object_property_del_child (
>      child=0x555557ddcf90, obj=0x55555685da10) at ../qom/object.c:645
>  #12 object_unparent (obj=0x555557ddcf90) at ../qom/object.c:664
>  #13 0x00005555558dc331 in pci_for_each_device_under_bus (
>      opaque=<optimized out>, fn=<optimized out>, bus=<optimized out>)
>      at ../hw/pci/pci.c:1654
> 
> [2]
> 
> Optimizer omits pci_qdev_unrealize, called by device_set_realized, and
> do_pci_unregister_device, called by pci_qdev_unrealize and caller of
> address_space_destroy.
> 
>  #0  address_space_destroy (as=0x555557ddd1b8)
>      at ../softmmu/memory.c:2840
>  #1  0x0000555555b4fc53 in device_set_realized (obj=0x555557ddcf90,
>       value=<optimized out>, errp=0x7fffeea8f1e0)
>      at ../hw/core/qdev.c:850
>  #2  0x0000555555b6eaa6 in property_set_bool (obj=0x555557ddcf90,
>       v=<optimized out>, name=<optimized out>, opaque=0x555556650ba0,
>      errp=0x7fffeea8f1e0) at ../qom/object.c:2255
>  #3  0x0000555555b70e07 in object_property_set (
>       obj=obj@entry=0x555557ddcf90,
>       name=name@entry=0x555555db99df "realized",
>       v=v@entry=0x7fffe46b7500,
>       errp=errp@entry=0x5555565bbf38 <error_abort>)
>      at ../qom/object.c:1400
>  #4  0x0000555555b73c5f in object_property_set_qobject (
>       obj=obj@entry=0x555557ddcf90,
>       name=name@entry=0x555555db99df "realized",
>       value=value@entry=0x7fffe44f6180,
>       errp=errp@entry=0x5555565bbf38 <error_abort>)
>      at ../qom/qom-qobject.c:28
>  #5  0x0000555555b71044 in object_property_set_bool (
>       obj=0x555557ddcf90, name=0x555555db99df "realized",
>       value=<optimized out>, errp=0x5555565bbf38 <error_abort>)
>      at ../qom/object.c:1470
>  #6  0x0000555555921cb7 in pcie_unplug_device (bus=<optimized out>,
>       dev=0x555557ddcf90,
>       opaque=<optimized out>) at /home/qemu/include/hw/qdev-core.h:17
>  #7  0x00005555558dc331 in pci_for_each_device_under_bus (
>       opaque=<optimized out>, fn=<optimized out>,
>       bus=<optimized out>) at ../hw/pci/pci.c:1654
> 
> [3]
> 
>  #0  virtio_device_unrealize (dev=0x555557de5120)
>      at ../hw/virtio/virtio.c:3680
>  #1  0x0000555555b4fc63 in device_set_realized (obj=0x555557de5120,
>      value=<optimized out>, errp=0x7fffee28df90)
>      at ../hw/core/qdev.c:850
>  #2  0x0000555555b6eab6 in property_set_bool (obj=0x555557de5120,
>      v=<optimized out>, name=<optimized out>, opaque=0x555556650ba0,
>      errp=0x7fffee28df90) at ../qom/object.c:2255
>  #3  0x0000555555b70e17 in object_property_set (
>      obj=obj@entry=0x555557de5120,
>      name=name@entry=0x555555db99ff "realized",
>      v=v@entry=0x7ffdd8035040,
>      errp=errp@entry=0x5555565bbf38 <error_abort>)
>      at ../qom/object.c:1400
>  #4  0x0000555555b73c6f in object_property_set_qobject (
>      obj=obj@entry=0x555557de5120,
>      name=name@entry=0x555555db99ff "realized",
>      value=value@entry=0x7ffdd8035020,
>      errp=errp@entry=0x5555565bbf38 <error_abort>)
>      at ../qom/qom-qobject.c:28
>  #5  0x0000555555b71054 in object_property_set_bool (
>      obj=0x555557de5120, name=name@entry=0x555555db99ff "realized",
>      value=value@entry=false, errp=0x5555565bbf38 <error_abort>)
>      at ../qom/object.c:1470
>  #6  0x0000555555b4edc5 in qdev_unrealize (dev=<optimized out>)
>      at ../hw/core/qdev.c:403
>  #7  0x0000555555b4c2a9 in bus_set_realized (obj=<optimized out>,
>      value=<optimized out>, errp=<optimized out>)
>      at ../hw/core/bus.c:204
>  #8  0x0000555555b6eab6 in property_set_bool (obj=0x555557de5098,
>      v=<optimized out>, name=<optimized out>, opaque=0x555557df04c0,
>      errp=0x7fffee28e0a0) at ../qom/object.c:2255
>  #9  0x0000555555b70e17 in object_property_set (
>      obj=obj@entry=0x555557de5098,
>      name=name@entry=0x555555db99ff "realized",
>      v=v@entry=0x7ffdd8034f50,
>      errp=errp@entry=0x5555565bbf38 <error_abort>)
>      at ../qom/object.c:1400
>  #10 0x0000555555b73c6f in object_property_set_qobject (
>      obj=obj@entry=0x555557de5098,
>      name=name@entry=0x555555db99ff "realized",
>      value=value@entry=0x7ffdd8020630,
>      errp=errp@entry=0x5555565bbf38 <error_abort>)
>      at ../qom/qom-qobject.c:28
>  #11 0x0000555555b71054 in object_property_set_bool (
>      obj=obj@entry=0x555557de5098,
>      name=name@entry=0x555555db99ff "realized",
>      value=value@entry=false, errp=0x5555565bbf38 <error_abort>)
>      at ../qom/object.c:1470
>  #12 0x0000555555b4c725 in qbus_unrealize (
>      bus=bus@entry=0x555557de5098) at ../hw/core/bus.c:178
>  #13 0x0000555555b4fc00 in device_set_realized (obj=0x555557ddcf90,
>      value=<optimized out>, errp=0x7fffee28e1e0)
>      at ../hw/core/qdev.c:844
>  #14 0x0000555555b6eab6 in property_set_bool (obj=0x555557ddcf90,
>      v=<optimized out>, name=<optimized out>, opaque=0x555556650ba0,
>      errp=0x7fffee28e1e0) at ../qom/object.c:2255
>  #15 0x0000555555b70e17 in object_property_set (
>      obj=obj@entry=0x555557ddcf90,
>      name=name@entry=0x555555db99ff "realized",
>      v=v@entry=0x7ffdd8020560,
>      errp=errp@entry=0x5555565bbf38 <error_abort>)
>      at ../qom/object.c:1400
>  #16 0x0000555555b73c6f in object_property_set_qobject (
>      obj=obj@entry=0x555557ddcf90,
>      name=name@entry=0x555555db99ff "realized",
>      value=value@entry=0x7ffdd8020540,
>      errp=errp@entry=0x5555565bbf38 <error_abort>)
>      at ../qom/qom-qobject.c:28
>  #17 0x0000555555b71054 in object_property_set_bool (
>      obj=0x555557ddcf90, name=0x555555db99ff "realized",
>      value=<optimized out>, errp=0x5555565bbf38 <error_abort>)
>      at ../qom/object.c:1470
>  #18 0x0000555555921cb7 in pcie_unplug_device (bus=<optimized out>,
>      dev=0x555557ddcf90, opaque=<optimized out>)
>      at /home/qemu/include/hw/qdev-core.h:17
>  #19 0x00005555558dc331 in pci_for_each_device_under_bus (
>      opaque=<optimized out>, fn=<optimized out>, bus=<optimized out>)
>      at ../hw/pci/pci.c:1654
> 
> Fixes: c611c76417f ("virtio: add MemoryListener to cache ring translations")
> Buglink: https://bugs.launchpad.net/qemu/+bug/1912846
> Signed-off-by: Eugenio Pérez <eperezma@redhat.com>

IMHO this time the backtrace is great but maybe too verbose.. but I think it's
ok.

Reviewed-by: Peter Xu <peterx@redhat.com>
Jason Wang Jan. 27, 2021, 3:54 a.m. UTC | #2
On 2021/1/26 下午11:40, Peter Xu wrote:
> On Mon, Jan 25, 2021 at 08:25:05PM +0100, Eugenio Pérez wrote:
>> Address space is destroyed without proper removal of its listeners with
>> current code. They are expected to be removed in
>> virtio_device_instance_finalize [1], but qemu calls it through
>> object_deinit, after address_space_destroy call through
>> device_set_realized [2].
>>
>> Move it to virtio_device_unrealize, called before device_set_realized
>> [3] and making it symmetric with memory_listener_register in
>> virtio_device_realize.
>>
>> v2: Delete no-op call of virtio_device_instance_finalize.
>>      Add backtraces.
> This can be dropped from commit.
>
>> [1]
>>
>>   #0  virtio_device_instance_finalize (obj=0x555557de5120)
>>       at /home/qemu/include/hw/virtio/virtio.h:71
>>   #1  0x0000555555b703c9 in object_deinit (type=0x555556639860,
>>        obj=<optimized out>) at ../qom/object.c:671
>>   #2  object_finalize (data=0x555557de5120) at ../qom/object.c:685
>>   #3  object_unref (objptr=0x555557de5120) at ../qom/object.c:1184
>>   #4  0x0000555555b4de9d in bus_free_bus_child (kid=0x555557df0660)
>>       at ../hw/core/qdev.c:55
>>   #5  0x0000555555c65003 in call_rcu_thread (opaque=opaque@entry=0x0)
>>       at ../util/rcu.c:281
>>
>> Queued by:
>>
>>   #0  bus_remove_child (bus=0x555557de5098,
>>       child=child@entry=0x555557de5120) at ../hw/core/qdev.c:60
>>   #1  0x0000555555b4ee31 in device_unparent (obj=<optimized out>)
>>       at ../hw/core/qdev.c:984
>>   #2  0x0000555555b70465 in object_finalize_child_property (
>>       obj=<optimized out>, name=<optimized out>, opaque=0x555557de5120)
>>       at ../qom/object.c:1725
>>   #3  0x0000555555b6fa17 in object_property_del_child (
>>       child=0x555557de5120, obj=0x555557ddcf90) at ../qom/object.c:645
>>   #4  object_unparent (obj=0x555557de5120) at ../qom/object.c:664
>>   #5  0x0000555555b4c071 in bus_unparent (obj=<optimized out>)
>>       at ../hw/core/bus.c:147
>>   #6  0x0000555555b70465 in object_finalize_child_property (
>>       obj=<optimized out>, name=<optimized out>, opaque=0x555557de5098)
>>       at ../qom/object.c:1725
>>   #7  0x0000555555b6fa17 in object_property_del_child (
>>       child=0x555557de5098, obj=0x555557ddcf90) at ../qom/object.c:645
>>   #8  object_unparent (obj=0x555557de5098) at ../qom/object.c:664
>>   #9  0x0000555555b4ee19 in device_unparent (obj=<optimized out>)
>>       at ../hw/core/qdev.c:981
>>   #10 0x0000555555b70465 in object_finalize_child_property (
>>       obj=<optimized out>, name=<optimized out>, opaque=0x555557ddcf90)
>>       at ../qom/object.c:1725
>>   #11 0x0000555555b6fa17 in object_property_del_child (
>>       child=0x555557ddcf90, obj=0x55555685da10) at ../qom/object.c:645
>>   #12 object_unparent (obj=0x555557ddcf90) at ../qom/object.c:664
>>   #13 0x00005555558dc331 in pci_for_each_device_under_bus (
>>       opaque=<optimized out>, fn=<optimized out>, bus=<optimized out>)
>>       at ../hw/pci/pci.c:1654
>>
>> [2]
>>
>> Optimizer omits pci_qdev_unrealize, called by device_set_realized, and
>> do_pci_unregister_device, called by pci_qdev_unrealize and caller of
>> address_space_destroy.
>>
>>   #0  address_space_destroy (as=0x555557ddd1b8)
>>       at ../softmmu/memory.c:2840
>>   #1  0x0000555555b4fc53 in device_set_realized (obj=0x555557ddcf90,
>>        value=<optimized out>, errp=0x7fffeea8f1e0)
>>       at ../hw/core/qdev.c:850
>>   #2  0x0000555555b6eaa6 in property_set_bool (obj=0x555557ddcf90,
>>        v=<optimized out>, name=<optimized out>, opaque=0x555556650ba0,
>>       errp=0x7fffeea8f1e0) at ../qom/object.c:2255
>>   #3  0x0000555555b70e07 in object_property_set (
>>        obj=obj@entry=0x555557ddcf90,
>>        name=name@entry=0x555555db99df "realized",
>>        v=v@entry=0x7fffe46b7500,
>>        errp=errp@entry=0x5555565bbf38 <error_abort>)
>>       at ../qom/object.c:1400
>>   #4  0x0000555555b73c5f in object_property_set_qobject (
>>        obj=obj@entry=0x555557ddcf90,
>>        name=name@entry=0x555555db99df "realized",
>>        value=value@entry=0x7fffe44f6180,
>>        errp=errp@entry=0x5555565bbf38 <error_abort>)
>>       at ../qom/qom-qobject.c:28
>>   #5  0x0000555555b71044 in object_property_set_bool (
>>        obj=0x555557ddcf90, name=0x555555db99df "realized",
>>        value=<optimized out>, errp=0x5555565bbf38 <error_abort>)
>>       at ../qom/object.c:1470
>>   #6  0x0000555555921cb7 in pcie_unplug_device (bus=<optimized out>,
>>        dev=0x555557ddcf90,
>>        opaque=<optimized out>) at /home/qemu/include/hw/qdev-core.h:17
>>   #7  0x00005555558dc331 in pci_for_each_device_under_bus (
>>        opaque=<optimized out>, fn=<optimized out>,
>>        bus=<optimized out>) at ../hw/pci/pci.c:1654
>>
>> [3]
>>
>>   #0  virtio_device_unrealize (dev=0x555557de5120)
>>       at ../hw/virtio/virtio.c:3680
>>   #1  0x0000555555b4fc63 in device_set_realized (obj=0x555557de5120,
>>       value=<optimized out>, errp=0x7fffee28df90)
>>       at ../hw/core/qdev.c:850
>>   #2  0x0000555555b6eab6 in property_set_bool (obj=0x555557de5120,
>>       v=<optimized out>, name=<optimized out>, opaque=0x555556650ba0,
>>       errp=0x7fffee28df90) at ../qom/object.c:2255
>>   #3  0x0000555555b70e17 in object_property_set (
>>       obj=obj@entry=0x555557de5120,
>>       name=name@entry=0x555555db99ff "realized",
>>       v=v@entry=0x7ffdd8035040,
>>       errp=errp@entry=0x5555565bbf38 <error_abort>)
>>       at ../qom/object.c:1400
>>   #4  0x0000555555b73c6f in object_property_set_qobject (
>>       obj=obj@entry=0x555557de5120,
>>       name=name@entry=0x555555db99ff "realized",
>>       value=value@entry=0x7ffdd8035020,
>>       errp=errp@entry=0x5555565bbf38 <error_abort>)
>>       at ../qom/qom-qobject.c:28
>>   #5  0x0000555555b71054 in object_property_set_bool (
>>       obj=0x555557de5120, name=name@entry=0x555555db99ff "realized",
>>       value=value@entry=false, errp=0x5555565bbf38 <error_abort>)
>>       at ../qom/object.c:1470
>>   #6  0x0000555555b4edc5 in qdev_unrealize (dev=<optimized out>)
>>       at ../hw/core/qdev.c:403
>>   #7  0x0000555555b4c2a9 in bus_set_realized (obj=<optimized out>,
>>       value=<optimized out>, errp=<optimized out>)
>>       at ../hw/core/bus.c:204
>>   #8  0x0000555555b6eab6 in property_set_bool (obj=0x555557de5098,
>>       v=<optimized out>, name=<optimized out>, opaque=0x555557df04c0,
>>       errp=0x7fffee28e0a0) at ../qom/object.c:2255
>>   #9  0x0000555555b70e17 in object_property_set (
>>       obj=obj@entry=0x555557de5098,
>>       name=name@entry=0x555555db99ff "realized",
>>       v=v@entry=0x7ffdd8034f50,
>>       errp=errp@entry=0x5555565bbf38 <error_abort>)
>>       at ../qom/object.c:1400
>>   #10 0x0000555555b73c6f in object_property_set_qobject (
>>       obj=obj@entry=0x555557de5098,
>>       name=name@entry=0x555555db99ff "realized",
>>       value=value@entry=0x7ffdd8020630,
>>       errp=errp@entry=0x5555565bbf38 <error_abort>)
>>       at ../qom/qom-qobject.c:28
>>   #11 0x0000555555b71054 in object_property_set_bool (
>>       obj=obj@entry=0x555557de5098,
>>       name=name@entry=0x555555db99ff "realized",
>>       value=value@entry=false, errp=0x5555565bbf38 <error_abort>)
>>       at ../qom/object.c:1470
>>   #12 0x0000555555b4c725 in qbus_unrealize (
>>       bus=bus@entry=0x555557de5098) at ../hw/core/bus.c:178
>>   #13 0x0000555555b4fc00 in device_set_realized (obj=0x555557ddcf90,
>>       value=<optimized out>, errp=0x7fffee28e1e0)
>>       at ../hw/core/qdev.c:844
>>   #14 0x0000555555b6eab6 in property_set_bool (obj=0x555557ddcf90,
>>       v=<optimized out>, name=<optimized out>, opaque=0x555556650ba0,
>>       errp=0x7fffee28e1e0) at ../qom/object.c:2255
>>   #15 0x0000555555b70e17 in object_property_set (
>>       obj=obj@entry=0x555557ddcf90,
>>       name=name@entry=0x555555db99ff "realized",
>>       v=v@entry=0x7ffdd8020560,
>>       errp=errp@entry=0x5555565bbf38 <error_abort>)
>>       at ../qom/object.c:1400
>>   #16 0x0000555555b73c6f in object_property_set_qobject (
>>       obj=obj@entry=0x555557ddcf90,
>>       name=name@entry=0x555555db99ff "realized",
>>       value=value@entry=0x7ffdd8020540,
>>       errp=errp@entry=0x5555565bbf38 <error_abort>)
>>       at ../qom/qom-qobject.c:28
>>   #17 0x0000555555b71054 in object_property_set_bool (
>>       obj=0x555557ddcf90, name=0x555555db99ff "realized",
>>       value=<optimized out>, errp=0x5555565bbf38 <error_abort>)
>>       at ../qom/object.c:1470
>>   #18 0x0000555555921cb7 in pcie_unplug_device (bus=<optimized out>,
>>       dev=0x555557ddcf90, opaque=<optimized out>)
>>       at /home/qemu/include/hw/qdev-core.h:17
>>   #19 0x00005555558dc331 in pci_for_each_device_under_bus (
>>       opaque=<optimized out>, fn=<optimized out>, bus=<optimized out>)
>>       at ../hw/pci/pci.c:1654
>>
>> Fixes: c611c76417f ("virtio: add MemoryListener to cache ring translations")
>> Buglink: https://bugs.launchpad.net/qemu/+bug/1912846
>> Signed-off-by: Eugenio Pérez <eperezma@redhat.com>
> IMHO this time the backtrace is great but maybe too verbose.. but I think it's
> ok.
>
> Reviewed-by: Peter Xu <peterx@redhat.com>


Acked-by: Jason Wang <jasowang@redhat.com>


>
Stefano Garzarella Jan. 27, 2021, 10:19 a.m. UTC | #3
On Mon, Jan 25, 2021 at 08:25:05PM +0100, Eugenio Pérez wrote:
>Address space is destroyed without proper removal of its listeners with
>current code. They are expected to be removed in
>virtio_device_instance_finalize [1], but qemu calls it through
>object_deinit, after address_space_destroy call through
>device_set_realized [2].
>
>Move it to virtio_device_unrealize, called before device_set_realized
>[3] and making it symmetric with memory_listener_register in
>virtio_device_realize.
>
>v2: Delete no-op call of virtio_device_instance_finalize.
>    Add backtraces.
>
>[1]
>
> #0  virtio_device_instance_finalize (obj=0x555557de5120)
>     at /home/qemu/include/hw/virtio/virtio.h:71
> #1  0x0000555555b703c9 in object_deinit (type=0x555556639860,
>      obj=<optimized out>) at ../qom/object.c:671
> #2  object_finalize (data=0x555557de5120) at ../qom/object.c:685
> #3  object_unref (objptr=0x555557de5120) at ../qom/object.c:1184
> #4  0x0000555555b4de9d in bus_free_bus_child (kid=0x555557df0660)
>     at ../hw/core/qdev.c:55
> #5  0x0000555555c65003 in call_rcu_thread (opaque=opaque@entry=0x0)
>     at ../util/rcu.c:281
>
>Queued by:
>
> #0  bus_remove_child (bus=0x555557de5098,
>     child=child@entry=0x555557de5120) at ../hw/core/qdev.c:60
> #1  0x0000555555b4ee31 in device_unparent (obj=<optimized out>)
>     at ../hw/core/qdev.c:984
> #2  0x0000555555b70465 in object_finalize_child_property (
>     obj=<optimized out>, name=<optimized out>, opaque=0x555557de5120)
>     at ../qom/object.c:1725
> #3  0x0000555555b6fa17 in object_property_del_child (
>     child=0x555557de5120, obj=0x555557ddcf90) at ../qom/object.c:645
> #4  object_unparent (obj=0x555557de5120) at ../qom/object.c:664
> #5  0x0000555555b4c071 in bus_unparent (obj=<optimized out>)
>     at ../hw/core/bus.c:147
> #6  0x0000555555b70465 in object_finalize_child_property (
>     obj=<optimized out>, name=<optimized out>, opaque=0x555557de5098)
>     at ../qom/object.c:1725
> #7  0x0000555555b6fa17 in object_property_del_child (
>     child=0x555557de5098, obj=0x555557ddcf90) at ../qom/object.c:645
> #8  object_unparent (obj=0x555557de5098) at ../qom/object.c:664
> #9  0x0000555555b4ee19 in device_unparent (obj=<optimized out>)
>     at ../hw/core/qdev.c:981
> #10 0x0000555555b70465 in object_finalize_child_property (
>     obj=<optimized out>, name=<optimized out>, opaque=0x555557ddcf90)
>     at ../qom/object.c:1725
> #11 0x0000555555b6fa17 in object_property_del_child (
>     child=0x555557ddcf90, obj=0x55555685da10) at ../qom/object.c:645
> #12 object_unparent (obj=0x555557ddcf90) at ../qom/object.c:664
> #13 0x00005555558dc331 in pci_for_each_device_under_bus (
>     opaque=<optimized out>, fn=<optimized out>, bus=<optimized out>)
>     at ../hw/pci/pci.c:1654
>
>[2]
>
>Optimizer omits pci_qdev_unrealize, called by device_set_realized, and
>do_pci_unregister_device, called by pci_qdev_unrealize and caller of
>address_space_destroy.
>
> #0  address_space_destroy (as=0x555557ddd1b8)
>     at ../softmmu/memory.c:2840
> #1  0x0000555555b4fc53 in device_set_realized (obj=0x555557ddcf90,
>      value=<optimized out>, errp=0x7fffeea8f1e0)
>     at ../hw/core/qdev.c:850
> #2  0x0000555555b6eaa6 in property_set_bool (obj=0x555557ddcf90,
>      v=<optimized out>, name=<optimized out>, opaque=0x555556650ba0,
>     errp=0x7fffeea8f1e0) at ../qom/object.c:2255
> #3  0x0000555555b70e07 in object_property_set (
>      obj=obj@entry=0x555557ddcf90,
>      name=name@entry=0x555555db99df "realized",
>      v=v@entry=0x7fffe46b7500,
>      errp=errp@entry=0x5555565bbf38 <error_abort>)
>     at ../qom/object.c:1400
> #4  0x0000555555b73c5f in object_property_set_qobject (
>      obj=obj@entry=0x555557ddcf90,
>      name=name@entry=0x555555db99df "realized",
>      value=value@entry=0x7fffe44f6180,
>      errp=errp@entry=0x5555565bbf38 <error_abort>)
>     at ../qom/qom-qobject.c:28
> #5  0x0000555555b71044 in object_property_set_bool (
>      obj=0x555557ddcf90, name=0x555555db99df "realized",
>      value=<optimized out>, errp=0x5555565bbf38 <error_abort>)
>     at ../qom/object.c:1470
> #6  0x0000555555921cb7 in pcie_unplug_device (bus=<optimized out>,
>      dev=0x555557ddcf90,
>      opaque=<optimized out>) at /home/qemu/include/hw/qdev-core.h:17
> #7  0x00005555558dc331 in pci_for_each_device_under_bus (
>      opaque=<optimized out>, fn=<optimized out>,
>      bus=<optimized out>) at ../hw/pci/pci.c:1654
>
>[3]
>
> #0  virtio_device_unrealize (dev=0x555557de5120)
>     at ../hw/virtio/virtio.c:3680
> #1  0x0000555555b4fc63 in device_set_realized (obj=0x555557de5120,
>     value=<optimized out>, errp=0x7fffee28df90)
>     at ../hw/core/qdev.c:850
> #2  0x0000555555b6eab6 in property_set_bool (obj=0x555557de5120,
>     v=<optimized out>, name=<optimized out>, opaque=0x555556650ba0,
>     errp=0x7fffee28df90) at ../qom/object.c:2255
> #3  0x0000555555b70e17 in object_property_set (
>     obj=obj@entry=0x555557de5120,
>     name=name@entry=0x555555db99ff "realized",
>     v=v@entry=0x7ffdd8035040,
>     errp=errp@entry=0x5555565bbf38 <error_abort>)
>     at ../qom/object.c:1400
> #4  0x0000555555b73c6f in object_property_set_qobject (
>     obj=obj@entry=0x555557de5120,
>     name=name@entry=0x555555db99ff "realized",
>     value=value@entry=0x7ffdd8035020,
>     errp=errp@entry=0x5555565bbf38 <error_abort>)
>     at ../qom/qom-qobject.c:28
> #5  0x0000555555b71054 in object_property_set_bool (
>     obj=0x555557de5120, name=name@entry=0x555555db99ff "realized",
>     value=value@entry=false, errp=0x5555565bbf38 <error_abort>)
>     at ../qom/object.c:1470
> #6  0x0000555555b4edc5 in qdev_unrealize (dev=<optimized out>)
>     at ../hw/core/qdev.c:403
> #7  0x0000555555b4c2a9 in bus_set_realized (obj=<optimized out>,
>     value=<optimized out>, errp=<optimized out>)
>     at ../hw/core/bus.c:204
> #8  0x0000555555b6eab6 in property_set_bool (obj=0x555557de5098,
>     v=<optimized out>, name=<optimized out>, opaque=0x555557df04c0,
>     errp=0x7fffee28e0a0) at ../qom/object.c:2255
> #9  0x0000555555b70e17 in object_property_set (
>     obj=obj@entry=0x555557de5098,
>     name=name@entry=0x555555db99ff "realized",
>     v=v@entry=0x7ffdd8034f50,
>     errp=errp@entry=0x5555565bbf38 <error_abort>)
>     at ../qom/object.c:1400
> #10 0x0000555555b73c6f in object_property_set_qobject (
>     obj=obj@entry=0x555557de5098,
>     name=name@entry=0x555555db99ff "realized",
>     value=value@entry=0x7ffdd8020630,
>     errp=errp@entry=0x5555565bbf38 <error_abort>)
>     at ../qom/qom-qobject.c:28
> #11 0x0000555555b71054 in object_property_set_bool (
>     obj=obj@entry=0x555557de5098,
>     name=name@entry=0x555555db99ff "realized",
>     value=value@entry=false, errp=0x5555565bbf38 <error_abort>)
>     at ../qom/object.c:1470
> #12 0x0000555555b4c725 in qbus_unrealize (
>     bus=bus@entry=0x555557de5098) at ../hw/core/bus.c:178
> #13 0x0000555555b4fc00 in device_set_realized (obj=0x555557ddcf90,
>     value=<optimized out>, errp=0x7fffee28e1e0)
>     at ../hw/core/qdev.c:844
> #14 0x0000555555b6eab6 in property_set_bool (obj=0x555557ddcf90,
>     v=<optimized out>, name=<optimized out>, opaque=0x555556650ba0,
>     errp=0x7fffee28e1e0) at ../qom/object.c:2255
> #15 0x0000555555b70e17 in object_property_set (
>     obj=obj@entry=0x555557ddcf90,
>     name=name@entry=0x555555db99ff "realized",
>     v=v@entry=0x7ffdd8020560,
>     errp=errp@entry=0x5555565bbf38 <error_abort>)
>     at ../qom/object.c:1400
> #16 0x0000555555b73c6f in object_property_set_qobject (
>     obj=obj@entry=0x555557ddcf90,
>     name=name@entry=0x555555db99ff "realized",
>     value=value@entry=0x7ffdd8020540,
>     errp=errp@entry=0x5555565bbf38 <error_abort>)
>     at ../qom/qom-qobject.c:28
> #17 0x0000555555b71054 in object_property_set_bool (
>     obj=0x555557ddcf90, name=0x555555db99ff "realized",
>     value=<optimized out>, errp=0x5555565bbf38 <error_abort>)
>     at ../qom/object.c:1470
> #18 0x0000555555921cb7 in pcie_unplug_device (bus=<optimized out>,
>     dev=0x555557ddcf90, opaque=<optimized out>)
>     at /home/qemu/include/hw/qdev-core.h:17
> #19 0x00005555558dc331 in pci_for_each_device_under_bus (
>     opaque=<optimized out>, fn=<optimized out>, bus=<optimized out>)
>     at ../hw/pci/pci.c:1654
>
>Fixes: c611c76417f ("virtio: add MemoryListener to cache ring translations")
>Buglink: https://bugs.launchpad.net/qemu/+bug/1912846
>Signed-off-by: Eugenio Pérez <eperezma@redhat.com>
>---
> hw/virtio/virtio.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
>diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
>index b308026596..1fd1917ca0 100644
>--- a/hw/virtio/virtio.c
>+++ b/hw/virtio/virtio.c
>@@ -3680,6 +3680,7 @@ static void virtio_device_unrealize(DeviceState *dev)
>     VirtIODevice *vdev = VIRTIO_DEVICE(dev);
>     VirtioDeviceClass *vdc = VIRTIO_DEVICE_GET_CLASS(dev);
>
>+    memory_listener_unregister(&vdev->listener);
>     virtio_bus_device_unplugged(vdev);
>
>     if (vdc->unrealize != NULL) {
>@@ -3710,7 +3711,6 @@ static void virtio_device_instance_finalize(Object *obj)
> {
>     VirtIODevice *vdev = VIRTIO_DEVICE(obj);
>
>-    memory_listener_unregister(&vdev->listener);
>     virtio_device_free_virtqueues(vdev);
>
>     g_free(vdev->config);
>-- 
>2.27.0
>
>

Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
diff mbox series

Patch

diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index b308026596..1fd1917ca0 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -3680,6 +3680,7 @@  static void virtio_device_unrealize(DeviceState *dev)
     VirtIODevice *vdev = VIRTIO_DEVICE(dev);
     VirtioDeviceClass *vdc = VIRTIO_DEVICE_GET_CLASS(dev);
 
+    memory_listener_unregister(&vdev->listener);
     virtio_bus_device_unplugged(vdev);
 
     if (vdc->unrealize != NULL) {
@@ -3710,7 +3711,6 @@  static void virtio_device_instance_finalize(Object *obj)
 {
     VirtIODevice *vdev = VIRTIO_DEVICE(obj);
 
-    memory_listener_unregister(&vdev->listener);
     virtio_device_free_virtqueues(vdev);
 
     g_free(vdev->config);