|
| From: | Laszlo Ersek |
| Subject: | Re: [RFC PATCH v2 20/44] i386/tdx: Parse tdx metadata and store the result into TdxGuestState |
| Date: | Tue, 11 Jan 2022 09:48:53 +0100 |
On 01/11/22 09:19, Laszlo Ersek wrote:
> 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
In that call tree, I ignored Reclaim()
[MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c]; Reclaim() is
called from more places than just from UpdateVariable().
In Reclaim(), we (roughly) have
Reclaim() [MdeModulePkg/Universal/Variable/RuntimeDxe/Variable.c]
FtwVariableSpace() [MdeModulePkg/Universal/Variable/RuntimeDxe/Reclaim.c]
FtwWrite()
[MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWrite.c]
QemuFlashWrite() [OvmfPkg/QemuFlashFvbServicesRuntimeDxe/QemuFlash.c]
For a bit more info on the internals of FtwWrite(), see the attached
message (I'd provide a URL, but Intel had killed the edk2-devel archives
on lists.01.org, and the other archives don't go back to 2014...)
Thanks
Laszlo
--- Begin Message ---Subject: Re: [edk2] Firmware Volume Block and Fault Tolerant Write question. Date: Mon, 21 Apr 2014 13:55:42 +0200 User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Thunderbird/24.4.0 On 04/18/14 21:32, Kirkendall, Garrett wrote: > Is there any good documentation for how the Fault Tolerant Write is > supposed to work? > > I understand that NV storage, FTW working space and FTW spare space are > supposed to be in the same Firmware Volume. > > I’m having trouble deciphering how big the FTW working and spare areas > should be in relation to the NV storage space. > > Also, in a bunch of places, it looks like the code was written such that > the working space must fit within one block size. What happens if need > space spanning multiple blocks? Below are parts from two functions that > end in an ASSERT because only one block gets read and returns an error > when the requested FVB->Read input size is larger than one block of data. If it's any help, here's a diagram I derived last December, while I was hunting down <https://github.com/tianocore/edk2/commit/06f1982a>: On 12/17/13 07:16, Laszlo Ersek wrote: > During reclaim, the following data movements take place (I'm skipping > the erasures and the in-memory buffer manipulations): > > +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ L: event log > LIVE | varstore |L|W| W: working block > +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ > > +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ > SPARE | | > +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ > > (1) copy LIVE to MyBuffer > (2) copy SPARE to SpareBuffer > (3) copy MyBuffer to SPARE > (4) copy SPARE to Buffer > (5) copy Buffer to LIVE > (6) copy SpareBuffer to SPARE (MyBuffer, SpareBuffer, and Buffer are temporary memory buffers.) In OVMF, the block size is 4K. The varstore is 14 blocks (56K), plus we got one block (4K) for the event log and one block (4K) for the working block. In total, 64K in the live half. The spare half is the same size, giving 128K total for the firmware volume. I'm also attaching the debug patch I wrote at that time for the FTW and auth variable services, plus its output (which I annotated during analysis) that helped me understand what was happening. Maybe you can reuse something from them. Laszlo
debug.diff
Description: Text Data
direct.txt
Description: Text document
--- End Message ---
| [Prev in Thread] | Current Thread | [Next in Thread] |