qemu/include/hw/virtio
David Hildenbrand 177f9b1ee4 virtio-mem: Expose device memory dynamically via multiple memslots if enabled
Having large virtio-mem devices that only expose little memory to a VM
is currently a problem: we map the whole sparse memory region into the
guest using a single memslot, resulting in one gigantic memslot in KVM.
KVM allocates metadata for the whole memslot, which can result in quite
some memory waste.

Assuming we have a 1 TiB virtio-mem device and only expose little (e.g.,
1 GiB) memory, we would create a single 1 TiB memslot and KVM has to
allocate metadata for that 1 TiB memslot: on x86, this implies allocating
a significant amount of memory for metadata:

(1) RMAP: 8 bytes per 4 KiB, 8 bytes per 2 MiB, 8 bytes per 1 GiB
    -> For 1 TiB: 2147483648 + 4194304 + 8192 = ~ 2 GiB (0.2 %)

    With the TDP MMU (cat /sys/module/kvm/parameters/tdp_mmu) this gets
    allocated lazily when required for nested VMs
(2) gfn_track: 2 bytes per 4 KiB
    -> For 1 TiB: 536870912 = ~512 MiB (0.05 %)
(3) lpage_info: 4 bytes per 2 MiB, 4 bytes per 1 GiB
    -> For 1 TiB: 2097152 + 4096 = ~2 MiB (0.0002 %)
(4) 2x dirty bitmaps for tracking: 2x 1 bit per 4 KiB page
    -> For 1 TiB: 536870912 = 64 MiB (0.006 %)

So we primarily care about (1) and (2). The bad thing is, that the
memory consumption *doubles* once SMM is enabled, because we create the
memslot once for !SMM and once for SMM.

Having a 1 TiB memslot without the TDP MMU consumes around:
* With SMM: 5 GiB
* Without SMM: 2.5 GiB
Having a 1 TiB memslot with the TDP MMU consumes around:
* With SMM: 1 GiB
* Without SMM: 512 MiB

... and that's really something we want to optimize, to be able to just
start a VM with small boot memory (e.g., 4 GiB) and a virtio-mem device
that can grow very large (e.g., 1 TiB).

Consequently, using multiple memslots and only mapping the memslots we
really need can significantly reduce memory waste and speed up
memslot-related operations. Let's expose the sparse RAM memory region using
multiple memslots, mapping only the memslots we currently need into our
device memory region container.

The feature can be enabled using "dynamic-memslots=on" and requires
"unplugged-inaccessible=on", which is nowadays the default.

Once enabled, we'll auto-detect the number of memslots to use based on the
memslot limit provided by the core. We'll use at most 1 memslot per
gigabyte. Note that our global limit of memslots accross all memory devices
is currently set to 256: even with multiple large virtio-mem devices,
we'd still have a sane limit on the number of memslots used.

The default is to not dynamically map memslot for now
("dynamic-memslots=off"). The optimization must be enabled manually,
because some vhost setups (e.g., hotplug of vhost-user devices) might be
problematic until we support more memslots especially in vhost-user backends.

Note that "dynamic-memslots=on" is just a hint that multiple memslots
*may* be used for internal optimizations, not that multiple memslots
*must* be used. The actual number of memslots that are used is an
internal detail: for example, once memslot metadata is no longer an
issue, we could simply stop optimizing for that. Migration source and
destination can differ on the setting of "dynamic-memslots".

Message-ID: <20230926185738.277351-17-david@redhat.com>
Reviewed-by: Maciej S. Szmigiero <maciej.szmigiero@oracle.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: David Hildenbrand <david@redhat.com>
2023-10-12 14:15:22 +02:00
..
vdpa-dev.h vdpa: add vdpa-dev support 2022-12-21 06:35:28 -05:00
vhost-backend.h vhost: Remove vhost_backend_can_merge() callback 2023-10-12 14:15:21 +02:00
vhost-scsi-common.h vhost-scsi: support inflight io track 2020-09-30 19:09:20 +02:00
vhost-scsi.h Use OBJECT_DECLARE_SIMPLE_TYPE when possible 2020-09-18 14:12:32 -04:00
vhost-user-blk.h vhost-user-blk: make 'config_wce' part of 'host_features' 2022-10-07 09:41:51 -04:00
vhost-user-device.h hw/virtio: add config support to vhost-user-device 2023-10-04 04:54:05 -04:00
vhost-user-fs.h Clean up ill-advised or unusual header guards 2022-05-11 16:50:01 +02:00
vhost-user-gpio.h vhost-user-gpio: Configure vhost_dev when connecting 2023-03-02 03:10:47 -05:00
vhost-user-i2c.h Clean up ill-advised or unusual header guards 2022-05-11 16:50:01 +02:00
vhost-user-rng.h Clean up ill-advised or unusual header guards 2022-05-11 16:50:01 +02:00
vhost-user-scmi.h hw/virtio: Add a protection against duplicate vu_scmi_stop calls 2023-08-03 16:06:49 -04:00
vhost-user-scsi.h Use OBJECT_DECLARE_SIMPLE_TYPE when possible 2020-09-18 14:12:32 -04:00
vhost-user-vsock.h Clean up ill-advised or unusual header guards 2022-05-11 16:50:01 +02:00
vhost-user.h vhost-user: add shared_object msg 2023-10-04 18:15:06 -04:00
vhost-vdpa.h vdpa: export vhost_vdpa_set_vring_ready 2023-10-04 04:54:19 -04:00
vhost-vsock-common.h virtio: drop name parameter for virtio_init() 2022-05-16 04:38:40 -04:00
vhost-vsock.h vhost-vsock: handle common features in vhost-vsock-common 2021-10-05 17:30:57 -04:00
vhost.h vhost: Add vhost_get_max_memslots() 2023-10-12 14:15:22 +02:00
virtio-access.h Replace TARGET_WORDS_BIGENDIAN 2022-04-06 10:50:37 +02:00
virtio-balloon.h Use OBJECT_DECLARE_SIMPLE_TYPE when possible 2020-09-18 14:12:32 -04:00
virtio-blk-common.h virtio-blk: move config size params to virtio-blk-common 2022-10-07 09:41:51 -04:00
virtio-blk.h virtio-blk: simplify virtio_blk_dma_restart_cb() 2023-01-23 15:01:23 -05:00
virtio-bus.h virtio-bus: introduce iommu_enabled() 2021-09-04 16:35:17 -04:00
virtio-crypto.h crypto: Introduce RSA algorithm 2022-06-16 12:54:58 -04:00
virtio-dmabuf.h hw/display: introduce virtio-dmabuf 2023-10-04 18:15:06 -04:00
virtio-gpu-bswap.h include/hw/virtio/virtio-gpu: Fix virtio-gpu with blob on big endian hosts 2023-08-23 12:06:44 +02:00
virtio-gpu-pci.h Use OBJECT_DECLARE_SIMPLE_TYPE when possible 2020-09-18 14:12:32 -04:00
virtio-gpu-pixman.h virtio-gpu: add a pixman helper header 2019-05-29 06:29:07 +02:00
virtio-gpu.h virtio-gpu: reset gfx resources in main thread 2023-08-07 15:45:45 +04:00
virtio-input.h virtio-input: add a virtio-mulitouch device 2023-05-28 13:08:25 +04:00
virtio-iommu.h virtio-iommu: Fix 64kB host page size VFIO device assignment 2023-07-10 18:59:32 -04:00
virtio-md-pci.h virtio-md-pci: Support unplug requests for compatible devices 2023-07-12 09:27:30 +02:00
virtio-mem.h virtio-mem: Expose device memory dynamically via multiple memslots if enabled 2023-10-12 14:15:22 +02:00
virtio-mmio.h include: Include headers where needed 2023-01-08 01:54:22 -05:00
virtio-net.h virtio-net: Expose MAX_VLAN 2023-10-04 04:54:09 -04:00
virtio-pci.h virtio-pci: add support for configure interrupt 2023-01-08 01:54:22 -05:00
virtio-pmem.h qapi: Restrict device memory commands to machine code 2020-09-29 15:41:36 +02:00
virtio-rng.h Use OBJECT_DECLARE_SIMPLE_TYPE when possible 2020-09-18 14:12:32 -04:00
virtio-scsi.h virtio-scsi: reset SCSI devices from main loop thread 2023-02-23 19:49:35 +01:00
virtio-serial.h Use OBJECT_DECLARE_SIMPLE_TYPE when possible 2020-09-18 14:12:32 -04:00
virtio.h include/hw/virtio: document some more usage of notifiers 2023-07-10 18:59:32 -04:00