This series implements the proper use of FEAT_MEC MECID registers in QEMU for all translation regimes. In physical hardware, MECID registers are used to select an encryption engine that transparently encrypts memory data per Realm (as FEAT_MEC is an extension of FEAT_RME).
The main idea of this series is to avoid actual data encryption. Instead, we store the MECID associated with each page during guest data store operations. On subsequent memory accesses, we verify whether the MECID in the register matches the stored MECID. If a MECID mismatch occurs, rather than returning encrypted data as on physical hardware, a substitute page filled with 0xdeadbeef is returned to mimic the hardware's behavior. I tested this series by booting Linux on up to three VMs simultaneously and verified that the MECIDs for each were set correctly. There is one remaining issue tho: when a VM is destroyed and another is launched in sequence, a MECID mismatch occurs, leading to an "Unexpected exception on CPU" in the host. Since the software stack is still under development, I cannot yet exclude this is not a firmware or KVM-related issue. Regardless, this needs to be addressed; however, before I dig further, I would appreciate feedback on the implementation proposed in this series. For testing this series you can: Get the stack to test FEAT_MEC either: Download the artifacts (tf-a + tf-rmm + linux/kvm + kvmtool) from: https://github.com/gromero/qemu-linux-stack/actions/runs/23274571242/artifacts/5998250548 Then unzip and untar in QEMU's build dir: $ unzip ./build.zip $ tar xvf build.tar.xz Or build them from scratch: $ git clone https://github.com/gromero/qemu-linux-stack.git --branch rme_mec --single-branch --depth 1 $ cd qemu-linux-stack && ./build.sh Files will be in ./out and should be copied to QEMU's build dir: 4.1M out/flash.bin 167M out/guest.ext4 167M out/host.ext4 38M out/Image 3.1M out/lkvm Build QEMU with this series applied Run QEMU system with FEAT_MEC enabled (mec=on) from the build dir: ./qemu-system-aarch64 -display none -vga none -chardev stdio,id=console -serial chardev:console -machine virt -cpu max,x-rme=on -smp 2 -m 2G -M virt,acpi=off,virtualization=on,secure=on,gic-version=3,mec=on -bios ./out/flash.bin -kernel ./out/Image -drive format=raw,file=./out/host.ext4,if=virtio -virtfs local,path=./,mount_tag=host,security_model=mapped,readonly=off -append 'nokaslr root=/dev/vda rw init=/init -- /bin/bash' Once in Linux, do (for 2 VMs, for example): # apt-get install tmux # tmux Use [CTRL-b] " [SPACE] to split the terminal horizontally Use [CTRL-b] UP/DOWN to move between the two windows In one window run: # /host/out/lkvm run --realm -m 256m --shared-mec 0 --restricted_mem --kernel /host/out/Image --disk /host/out/guest.ext4 --params "root=/dev/vda rw init=/init" Then [CTRL-B] UP to move to the other window Then boot another VM: # /host/out/lkvm run --realm -m 256m --shared-mec 0 --restricted_mem --kernel /host/out/Image --disk /host/out/guest.ext4 --params "root=/dev/vda rw init=/init" Wait for the VMs to boot I added a patch to the series, "Print MECID if not zero [TO BE DISCARDED]", that can be used for printing the MECIDs used by the VMs. It will print a bunch of messages like: MECID (in register) stored for va = fffffffffffa7000 pa = 630d5000 is 3 [...] where one can observe different MECIDs being used the VMs, like 3 and 4. Just mind that the prints can slow down QEMU and cause CPU stalls on Linux. Cheers, Gustavo Gustavo Romero (7): target/arm: Flush TLB on MECID write target/cpu: Add two new address spaces for FEAT_MEC memattrs: Add new attribute 'encrypted' target/arm/cpu: Add FEAT_MEC object properties hw/arm/virt: Add machine option 'mec' target/arm/ptw: Add MECID checks target/arm/ptw: Print MECID if not zero [TO BE DISCARDED] hw/arm/virt.c | 76 ++++++++++++++ include/exec/memattrs.h | 7 ++ include/hw/arm/virt.h | 1 + target/arm/cpu.c | 20 ++++ target/arm/cpu.h | 14 ++- target/arm/helper.c | 2 + target/arm/internals.h | 2 + target/arm/ptw.c | 218 +++++++++++++++++++++++++++++++++++++++- 8 files changed, 337 insertions(+), 3 deletions(-) -- 2.34.1
