On 01/10/22 13:09, Xiaoyao Li wrote: > On 1/10/2022 7:01 PM, Gerd Hoffmann wrote: >>>> If you go without pflash, then you likely will not have a >>>> standards-conformant UEFI variable store. (Unless you reimplement >>>> the variable arch protocols in edk2 on top of something else than >>>> the Fault Tolerant Write and Firmware Volume Block protocols.) >>>> Whether a conformant UEFI varstore matters to you (or to TDX in >>>> general) is something I can't comment on. >>> >>> Thanks for your reply! Laszlo >>> >>> regarding "standards-conformant UEFI variable store", I guess you >>> mean the >>> change to UEFI non-volatile variables needs to be synced back to the >>> OVMF_VARS.fd file. right? >> >> Yes. UEFI variables are expected to be persistent, and syncing to >> OVMF_VARS.fd handles that. > > Further question. > > Is it achieved via read-only memslot that when UEFI variable gets > changed, it exits to QEMU with KVM_EXIT_MMIO due to read-only memslot > so QEMU can sync the change to OVMF_VAR.fd? Yes. When the flash device is in "romd_mode", that's when a readonly KVM memslot is used. In this case, the guest can read and execute from the memory region in question, only writes trap to QEMU. Such a write (WRITE_BYTE_CMD) is what the guest's flash driver uses to flip the flash device out of "romd_mode". When the flash device is not in "romd_mode", then no KVM memslot is used at all, and both reads and writes trap to QEMU. Once the flash programming is done, the guest's flash driver issues a particular write command (READ_ARRAY_CMD) that flips the device back to "romd_mode" (and then the readonly KVM memslot is re-established). Here's a rough call tree (for the non-SMM case, updating a non-authenticated non-volatile variable): VariableServiceSetVariable() [MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c] UpdateVariable() [MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c] UpdateVariableStore() [MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c] FvbProtocolWrite() [OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FwBlockService.c] QemuFlashWrite() [OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlash.c] QemuFlashPtrWrite (WRITE_BYTE_CMD /* 0x10 */) QEMU: pflash_write() [hw/block/pflash_cfi01.c] (wcycle == 0) memory_region_rom_device_set_romd(false) [softmmu/memory.c] ... kvm_region_del() [accel/kvm/kvm-all.c] kvm_set_phys_mem(false) [accel/kvm/kvm-all.c] /* unregister the slot */ /* Single Byte Program */ wcycle++ QemuFlashPtrWrite (Buffer[Loop]) QEMU: pflash_write() [hw/block/pflash_cfi01.c] (wcycle == 1) /* Single Byte Program */ pflash_data_write() [hw/block/pflash_cfi01.c] pflash_update() [hw/block/pflash_cfi01.c] blk_pwrite() [block/block-backend.c] wcycle = 0 QemuFlashPtrWrite (READ_ARRAY_CMD /* 0xff */) QEMU: pflash_write() [hw/block/pflash_cfi01.c] (wcycle == 0) memory_region_rom_device_set_romd(false) [softmmu/memory.c] /* no actual change */ /* Read Array */ memory_region_rom_device_set_romd(true) [softmmu/memory.c] kvm_region_add() [accel/kvm/kvm-all.c] kvm_set_phys_mem(true) [accel/kvm/kvm-all.c] /* register the new slot */ kvm_mem_flags() [accel/kvm/kvm-all.c] ... memory_region_is_romd() ... [include/exec/memory.h] flags |= KVM_MEM_READONLY Thanks Laszlo