Hi
On Tue, Mar 10, 2026 at 6:35 AM Chenyi Qiang <[email protected]> wrote:
>
>
>
> On 2/26/2026 9:59 PM, [email protected] wrote:
> > From: Marc-André Lureau <[email protected]>
> >
> > Hi,
> >
> > This is an attempt to fix the incompatibility of virtio-mem with
> > confidential
> > VMs. The solution implements what was discussed earlier with D. Hildenbrand:
> > https://patchwork.ozlabs.org/project/qemu-devel/patch/[email protected]/#3502238
> >
> > The first patches are misc cleanups. Then some code refactoring to have
> > split a
> > manager/source. And finally, the manager learns to deal with multiple
> > sources.
> >
> > I haven't done thorough testing. I only launched a SEV guest with a
> > virtio-mem
> > device. It would be nice to have more tests for those scenarios with
> > VFIO/virtio-mem/confvm.. In any case, review & testing needed!
>
> Is this series aimed to enable virtio-mem (memory hotplug) in a confidential
> VM?
> I tested it within a TD guest using the qemu command:
>
> qemu-system-x86_64
> ...
> -m 2G,maxmem=10G \
> -smp sockets=1,cores=2 \
> -object memory-backend-ram,id=mem0,size=2G \
> -numa node,nodeid=0,cpus=0-1,memdev=mem0 \
> -object memory-backend-ram,id=vmem0,size=8G \
> -device virtio-mem-pci,id=vm0,memdev=vmem0,node=0,requested-size=300M
> \
> -object tdx-guest,id=tdx \
> -machine q35,kernel_irqchip=split,hpet=off,memory-encryption=tdx \
> ...
>
> The TD VM will exit with the error when the guest kernel loads the virtio-mem
> driver:
>
> kvm_intel: Guest access before accepting 0x108008000 on vCPU 0
>
> I think it still lacks some support to accept the TD guest memory before
> using it.
>
It becomes increasingly hard to provide easy to setup reproducibe
environments.. but here is the libvirt qemu command I just tested
succesfully against:
qemu-system-x86_64 -name guest=rhel10,debug-threads=on -S -object
{"qom-type":"secret","id":"masterKey0","format":"raw","file":"/home/elmarco/.config/libvirt/qemu/lib/domain-3-rhel10/master-key.aes"}
-machine
pc-q35-10.1,usb=off,smm=off,dump-guest-core=off,confidential-guest-support=lsec0,hpet=off,acpi=on
-accel kvm -cpu host,migratable=on -bios
/usr/share/edk2/ovmf/OVMF.inteltdx.fd -m
size=4096000k,slots=1,maxmem=8192000k -overcommit mem-lock=off -smp
2,sockets=2,cores=1,threads=1 -object
{"qom-type":"memory-backend-ram","id":"ram-node0","size":4194304000}
-numa node,nodeid=0,cpus=0-1,memdev=ram-node0 -uuid
0f3e6b74-80e3-45e7-a0e6-ae7dfc897606 -display none -no-user-config
-nodefaults -chardev socket,id=charmonitor,fd=23,server=on,wait=off
-mon chardev=charmonitor,id=monitor,mode=control -rtc
base=utc,driftfix=slew -global kvm-pit.lost_tick_policy=delay
-no-shutdown -global ICH9-LPC.disable_s3=1 -global
ICH9-LPC.disable_s4=1 -boot strict=on -device
{"driver":"pcie-root-port","port":8,"chassis":1,"id":"pci.1","bus":"pcie.0","multifunction":true,"addr":"0x1"}
-device
{"driver":"pcie-root-port","port":9,"chassis":2,"id":"pci.2","bus":"pcie.0","addr":"0x1.0x1"}
-device
{"driver":"pcie-root-port","port":10,"chassis":3,"id":"pci.3","bus":"pcie.0","addr":"0x1.0x2"}
-device
{"driver":"pcie-root-port","port":11,"chassis":4,"id":"pci.4","bus":"pcie.0","addr":"0x1.0x3"}
-device
{"driver":"pcie-root-port","port":12,"chassis":5,"id":"pci.5","bus":"pcie.0","addr":"0x1.0x4"}
-device
{"driver":"pcie-root-port","port":13,"chassis":6,"id":"pci.6","bus":"pcie.0","addr":"0x1.0x5"}
-device
{"driver":"pcie-root-port","port":14,"chassis":7,"id":"pci.7","bus":"pcie.0","addr":"0x1.0x6"}
-device
{"driver":"pcie-root-port","port":15,"chassis":8,"id":"pci.8","bus":"pcie.0","addr":"0x1.0x7"}
-device
{"driver":"pcie-root-port","port":16,"chassis":9,"id":"pci.9","bus":"pcie.0","multifunction":true,"addr":"0x2"}
-device
{"driver":"pcie-root-port","port":17,"chassis":10,"id":"pci.10","bus":"pcie.0","addr":"0x2.0x1"}
-device
{"driver":"pcie-root-port","port":18,"chassis":11,"id":"pci.11","bus":"pcie.0","addr":"0x2.0x2"}
-device
{"driver":"pcie-root-port","port":19,"chassis":12,"id":"pci.12","bus":"pcie.0","addr":"0x2.0x3"}
-device
{"driver":"pcie-root-port","port":20,"chassis":13,"id":"pci.13","bus":"pcie.0","addr":"0x2.0x4"}
-device
{"driver":"pcie-root-port","port":21,"chassis":14,"id":"pci.14","bus":"pcie.0","addr":"0x2.0x5"}
-device
{"driver":"qemu-xhci","p2":15,"p3":15,"id":"usb","bus":"pci.2","addr":"0x0"}
-device
{"driver":"virtio-serial-pci","id":"virtio-serial0","bus":"pci.3","addr":"0x0"}
-object
{"qom-type":"memory-backend-ram","id":"memvirtiomem0","reserve":false,"size":4194304000}
-device
{"driver":"virtio-mem-pci","node":0,"block-size":2097152,"memdev":"memvirtiomem0","id":"virtiomem0","bus":"pci.7","addr":"0x0"}
-blockdev
{"driver":"file","filename":"/home/elmarco/rhel-10.qcow2","node-name":"libvirt-1-storage","auto-read-only":true,"discard":"unmap"}
-blockdev
{"node-name":"libvirt-1-format","read-only":false,"driver":"qcow2","file":"libvirt-1-storage","backing":null}
-device
{"driver":"virtio-blk-pci","bus":"pci.4","addr":"0x0","drive":"libvirt-1-format","id":"virtio-disk0","bootindex":1}
-netdev {"type":"user","id":"hostnet0"} -device
{"driver":"virtio-net-pci","netdev":"hostnet0","id":"net0","mac":"52:54:00:82:08:40","bus":"pci.1","addr":"0x0"}
-chardev pty,id=charserial0 -device
{"driver":"isa-serial","chardev":"charserial0","id":"serial0","index":0}
-chardev socket,id=charchannel0,fd=22,server=on,wait=off -device
{"driver":"virtserialport","bus":"virtio-serial0.0","nr":1,"chardev":"charchannel0","id":"channel0","name":"org.qemu.guest_agent.0"}
-chardev
socket,id=chrtpm,path=/run/user/1006/libvirt/qemu/run/swtpm/3-rhel10-swtpm.sock
-tpmdev emulator,id=tpm-tpm0,chardev=chrtpm -device
{"driver":"tpm-crb","tpmdev":"tpm-tpm0","id":"tpm0"} -audiodev
{"id":"audio1","driver":"none"} -global ICH9-LPC.noreboot=off
-watchdog-action reset -device
{"driver":"virtio-balloon-pci","id":"balloon0","bus":"pci.5","addr":"0x0"}
-object {"qom-type":"rng-random","id":"objrng0","filename":"/dev/urandom"}
-device
{"driver":"virtio-rng-pci","rng":"objrng0","id":"rng0","bus":"pci.6","addr":"0x0"}
-object
{"qom-type":"tdx-guest","id":"lsec0","quote-generation-socket":{"type":"unix","path":"/var/run/tdx-qgs/qgs.socket"},"attributes":268435456}
-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny
-msg timestamp=on
Then I hotplugged some mem:
virsh --connect qemu:///session update-memory-device rhel10
--requested-size 2GiB
[ 166.228943] virtio_mem virtio5: plugged size: 0x0
[ 166.231784] virtio_mem virtio5: requested size: 0x80000000
[root@rhel10-server ~]# lsmem
RANGE SIZE STATE REMOVABLE BLOCK
0x0000000000000000-0x000000007fffffff 2G online yes 0-15
0x0000000100000000-0x00000001ffffffff 4G online yes 32-63
Memory block size: 128M
Total online memory: 6G
Total offline memory: 0B
The host kernel used is experimental; it's a patched version of
6.19.0-rc8 that I don't have the details)
> >
> > (should fix https://issues.redhat.com/browse/RHEL-131968)
> >
> > v3: issues found by Cédric
> > - fix assertion error on shutdown, due to rcu-defer cleanup
> > - fix API doc warnings
> >
> > v2:
> > - drop replay_{populated,discarded} from source, suggested by Peter Xu
> > - add extra manager cleanup
> > - add r-b tags for preliminary patches
> >
> > thanks
> >
> > Marc-André Lureau (15):
> > system/rba: use DIV_ROUND_UP
> > memory: drop RamDiscardListener::double_discard_supported
> > virtio-mem: use warn_report_err_once()
> > system/memory: minor doc fix
> > kvm: replace RamDicardManager by the RamBlockAttribute
> > system/memory: split RamDiscardManager into source and manager
> > system/memory: move RamDiscardManager to separate compilation unit
> > system/memory: constify section arguments
> > system/ram-discard-manager: implement replay via is_populated
> > iteration
> > virtio-mem: remove replay_populated/replay_discarded implementation
> > system/ram-discard-manager: drop replay from source interface
> > system/memory: implement RamDiscardManager multi-source aggregation
> > system/physmem: destroy ram block attributes before RCU-deferred
> > reclaim
> > system/memory: add RamDiscardManager reference counting and cleanup
> > tests: add unit tests for RamDiscardManager multi-source aggregation
> >
> > include/hw/vfio/vfio-container.h | 2 +-
> > include/hw/vfio/vfio-cpr.h | 2 +-
> > include/hw/virtio/virtio-mem.h | 3 -
> > include/system/memory.h | 287 +----
> > include/system/ram-discard-manager.h | 358 ++++++
> > include/system/ramblock.h | 3 +-
> > accel/kvm/kvm-all.c | 2 +-
> > hw/vfio/cpr-legacy.c | 4 +-
> > hw/vfio/listener.c | 12 +-
> > hw/virtio/virtio-mem.c | 290 +----
> > migration/ram.c | 6 +-
> > system/memory.c | 83 +-
> > system/memory_mapping.c | 4 +-
> > system/physmem.c | 2 +-
> > system/ram-block-attributes.c | 279 +----
> > system/ram-discard-manager.c | 612 +++++++++
> > tests/unit/test-ram-discard-manager-stubs.c | 48 +
> > tests/unit/test-ram-discard-manager.c | 1234 +++++++++++++++++++
> > system/meson.build | 1 +
> > tests/unit/meson.build | 8 +-
> > 20 files changed, 2361 insertions(+), 879 deletions(-)
> > create mode 100644 include/system/ram-discard-manager.h
> > create mode 100644 system/ram-discard-manager.c
> > create mode 100644 tests/unit/test-ram-discard-manager-stubs.c
> > create mode 100644 tests/unit/test-ram-discard-manager.c
> >
>