Skip to content

destroying a vCPU will leak its AddressSpaces

(I have a fix for this; I'm filing the issue to provide a record of the details.)

At the moment every vCPU creates at least one AddressSpace via cpu_address_space_init() when it is realized, but we never free these when the vCPU is unrealized, resulting in a memory leak for a vCPU hot-unplug. For example, if you build QEMU with the clang AddressSanitizer and then do a hot-plug followed by hot-unplug as documented in https://www.qemu.org/docs/master/system/cpu-hotplug.html then you get this report of a leak:

Direct leak of 216 byte(s) in 1 object(s) allocated from:
    #0 0x56546235cfd8 in __interceptor_calloc (/mnt/nvmedisk/linaro/qemu-from-laptop/qemu/build/asan/qemu-system-x86_64+0x218efd8) (BuildId: 082eeb31b1b4dfb6bc12f4)
    #1 0x7f8520180c50 in g_malloc0 debian/build/deb/../../../glib/gmem.c:161:13
    #2 0x565464560213 in cpu_address_space_init /mnt/nvmedisk/linaro/qemu-from-laptop/qemu/build/asan/../../system/physmem.c:765:25
    #3 0x5654635bdca9 in qemu_init_vcpu /mnt/nvmedisk/linaro/qemu-from-laptop/qemu/build/asan/../../system/cpus.c:679:9
    #4 0x565463eb545f in x86_cpu_realizefn /mnt/nvmedisk/linaro/qemu-from-laptop/qemu/build/asan/../../target/i386/cpu.c:7834:5
    #5 0x5654647c8b25 in device_set_realized /mnt/nvmedisk/linaro/qemu-from-laptop/qemu/build/asan/../../hw/core/qdev.c:510:13
    #6 0x5654647f03eb in property_set_bool /mnt/nvmedisk/linaro/qemu-from-laptop/qemu/build/asan/../../qom/object.c:2354:5
    #7 0x5654647e9065 in object_property_set /mnt/nvmedisk/linaro/qemu-from-laptop/qemu/build/asan/../../qom/object.c:1463:5
    #8 0x5654647fd0d9 in object_property_set_qobject /mnt/nvmedisk/linaro/qemu-from-laptop/qemu/build/asan/../../qom/qom-qobject.c:28:10
    #9 0x5654647e9dbd in object_property_set_bool /mnt/nvmedisk/linaro/qemu-from-laptop/qemu/build/asan/../../qom/object.c:1533:15
    #10 0x5654647c2000 in qdev_realize /mnt/nvmedisk/linaro/qemu-from-laptop/qemu/build/asan/../../hw/core/qdev.c:291:12
    #11 0x5654635e2541 in qdev_device_add_from_qdict /mnt/nvmedisk/linaro/qemu-from-laptop/qemu/build/asan/../../system/qdev-monitor.c:719:10
    #12 0x5654635e4bbf in qdev_device_add /mnt/nvmedisk/linaro/qemu-from-laptop/qemu/build/asan/../../system/qdev-monitor.c:738:11
    #13 0x5654635e577b in qmp_device_add /mnt/nvmedisk/linaro/qemu-from-laptop/qemu/build/asan/../../system/qdev-monitor.c:863:11
    #14 0x565465295159 in do_qmp_dispatch_bh /mnt/nvmedisk/linaro/qemu-from-laptop/qemu/build/asan/../../qapi/qmp-dispatch.c:128:5
    #15 0x565465375941 in aio_bh_call /mnt/nvmedisk/linaro/qemu-from-laptop/qemu/build/asan/../../util/async.c:171:5
    #16 0x56546537681c in aio_bh_poll /mnt/nvmedisk/linaro/qemu-from-laptop/qemu/build/asan/../../util/async.c:218:13
    #17 0x5654652cf2a8 in aio_dispatch /mnt/nvmedisk/linaro/qemu-from-laptop/qemu/build/asan/../../util/aio-posix.c:423:5
    #18 0x56546537d7de in aio_ctx_dispatch /mnt/nvmedisk/linaro/qemu-from-laptop/qemu/build/asan/../../util/async.c:360:5
    #19 0x7f8520177d3a in g_main_dispatch debian/build/deb/../../../glib/gmain.c:3419:28
    #20 0x7f8520177d3a in g_main_context_dispatch debian/build/deb/../../../glib/gmain.c:4137:7
    #21 0x5654653815e9 in glib_pollfds_poll /mnt/nvmedisk/linaro/qemu-from-laptop/qemu/build/asan/../../util/main-loop.c:287:9
    #22 0x56546537ff23 in os_host_main_loop_wait /mnt/nvmedisk/linaro/qemu-from-laptop/qemu/build/asan/../../util/main-loop.c:310:5
    #23 0x56546537faec in main_loop_wait /mnt/nvmedisk/linaro/qemu-from-laptop/qemu/build/asan/../../util/main-loop.c:589:11
    #24 0x565463602917 in qemu_main_loop /mnt/nvmedisk/linaro/qemu-from-laptop/qemu/build/asan/../../system/runstate.c:801:9
    #25 0x565464ff6bac in qemu_default_main /mnt/nvmedisk/linaro/qemu-from-laptop/qemu/build/asan/../../system/main.c:37:14
    #26 0x565464ff6bf7 in main /mnt/nvmedisk/linaro/qemu-from-laptop/qemu/build/asan/../../system/main.c:48:12
    #27 0x7f851e007d8f in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16
    #28 0x7f851e007e3f in __libc_start_main csu/../csu/libc-start.c:392:3

To fix this we should arrange to dispose of the AddressSpaces when the CPU is unrealized. We should do this in a target-agnostic bit of code so that we don't need to repeat the same fix for every guest architecture.

This is a very long-standing leak and it's not a huge one, so this doesn't need to be fixed for 9.1 IMHO.

To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information