Message ID | 20220317135913.2166202-18-xiaoyao.li@intel.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | TDX QEMU support | expand |
Hi, On 17/3/22 14:58, Xiaoyao Li wrote: > TDX VM needs to boot with Trust Domain Virtual Firmware (TDVF). Unlike > that OVMF is mapped as rom device, TDVF needs to be mapped as private > memory. This is because TDX architecture doesn't provide read-only > capability for VMM, and it doesn't support instruction emulation due > to guest memory and registers are not accessible for VMM. > > On the other hand, OVMF can work as TDVF, which is usually configured > as pflash device in QEMU. To keep the same usage (QEMU parameter), > introduce ram_mode to pflash for TDVF. When it's creating a TDX VM, > ram_mode will be enabled automatically that map the firmware as RAM. > > Note, this implies two things: > 1. TDVF (OVMF) is not read-only (write-protected). > > 2. It doesn't support non-volatile UEFI variables as what pflash > supports that the change to non-volatile UEFI variables won't get > synced back to backend vars.fd file. > > Signed-off-by: Xiaoyao Li <xiaoyao.li@intel.com> > --- > hw/block/pflash_cfi01.c | 25 ++++++++++++++++++------- > hw/i386/pc_sysfw.c | 14 +++++++++++--- > 2 files changed, 29 insertions(+), 10 deletions(-) If you don't need a pflash device, don't use it: simply map your nvram region as ram in your machine. No need to clutter the pflash model like that. NAcked-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
On 3/18/2022 10:07 PM, Philippe Mathieu-Daudé wrote: > Hi, > > On 17/3/22 14:58, Xiaoyao Li wrote: >> TDX VM needs to boot with Trust Domain Virtual Firmware (TDVF). Unlike >> that OVMF is mapped as rom device, TDVF needs to be mapped as private >> memory. This is because TDX architecture doesn't provide read-only >> capability for VMM, and it doesn't support instruction emulation due >> to guest memory and registers are not accessible for VMM. >> >> On the other hand, OVMF can work as TDVF, which is usually configured >> as pflash device in QEMU. To keep the same usage (QEMU parameter), >> introduce ram_mode to pflash for TDVF. When it's creating a TDX VM, >> ram_mode will be enabled automatically that map the firmware as RAM. >> >> Note, this implies two things: >> 1. TDVF (OVMF) is not read-only (write-protected). >> >> 2. It doesn't support non-volatile UEFI variables as what pflash >> supports that the change to non-volatile UEFI variables won't get >> synced back to backend vars.fd file. >> >> Signed-off-by: Xiaoyao Li <xiaoyao.li@intel.com> >> --- >> hw/block/pflash_cfi01.c | 25 ++++++++++++++++++------- >> hw/i386/pc_sysfw.c | 14 +++++++++++--- >> 2 files changed, 29 insertions(+), 10 deletions(-) > > If you don't need a pflash device, don't use it: simply map your nvram > region as ram in your machine. No need to clutter the pflash model like > that. I know it's dirty to hack the pflash device. The purpose is to make the user interface unchanged that people can still use -drive if=pflash,format=raw,unit=0,file=/path/to/OVMF_CODE.fd -drive if=pflash,format=raw,unit=1,file=/path/to/OVMF_VARS.fd to create TD guest. I can go back to use generic loader[1] to load TDVF in v2. [1] https://lore.kernel.org/qemu-devel/acaf651389c3f407a9d6d0a2e943daf0a85bb5fc.1625704981.git.isaku.yamahata@intel.com/ > NAcked-by: Philippe Mathieu-Daudé <f4bug@amsat.org> >
On Mon, Mar 21, 2022 at 04:54:51PM +0800, Xiaoyao Li <xiaoyao.li@intel.com> wrote: > On 3/18/2022 10:07 PM, Philippe Mathieu-Daudé wrote: > > Hi, > > > > On 17/3/22 14:58, Xiaoyao Li wrote: > > > TDX VM needs to boot with Trust Domain Virtual Firmware (TDVF). Unlike > > > that OVMF is mapped as rom device, TDVF needs to be mapped as private > > > memory. This is because TDX architecture doesn't provide read-only > > > capability for VMM, and it doesn't support instruction emulation due > > > to guest memory and registers are not accessible for VMM. > > > > > > On the other hand, OVMF can work as TDVF, which is usually configured > > > as pflash device in QEMU. To keep the same usage (QEMU parameter), > > > introduce ram_mode to pflash for TDVF. When it's creating a TDX VM, > > > ram_mode will be enabled automatically that map the firmware as RAM. > > > > > > Note, this implies two things: > > > ?? 1. TDVF (OVMF) is not read-only (write-protected). > > > > > > ?? 2. It doesn't support non-volatile UEFI variables as what pflash > > > ???????? supports that the change to non-volatile UEFI variables won't get > > > ???????? synced back to backend vars.fd file. > > > > > > Signed-off-by: Xiaoyao Li <xiaoyao.li@intel.com> > > > --- > > > ?? hw/block/pflash_cfi01.c | 25 ++++++++++++++++++------- > > > ?? hw/i386/pc_sysfw.c?????????? | 14 +++++++++++--- > > > ?? 2 files changed, 29 insertions(+), 10 deletions(-) > > > > If you don't need a pflash device, don't use it: simply map your nvram > > region as ram in your machine. No need to clutter the pflash model like > > that. > > I know it's dirty to hack the pflash device. The purpose is to make the user > interface unchanged that people can still use > > -drive if=pflash,format=raw,unit=0,file=/path/to/OVMF_CODE.fd > -drive if=pflash,format=raw,unit=1,file=/path/to/OVMF_VARS.fd > > to create TD guest. For the compatibility for qemu command line, you don't have to modify pflash device. Don't instantiate pflash at pc_system_flash_create(), and at pc_system_firmware_init(), you can retrieve necessary parameters, and then populate memory. Although it's still hacky, it would be cleaner a bit.
Hi, > > If you don't need a pflash device, don't use it: simply map your nvram > > region as ram in your machine. No need to clutter the pflash model like > > that. Using the pflash device for something which isn't actually flash looks a bit silly indeed. > > I know it's dirty to hack the pflash device. The purpose is to make the user > interface unchanged that people can still use > > -drive if=pflash,format=raw,unit=0,file=/path/to/OVMF_CODE.fd > -drive if=pflash,format=raw,unit=1,file=/path/to/OVMF_VARS.fd > > to create TD guest. Well, if persistent vars are not supported anyway there is little reason to split the firmware into CODE and VARS files. You can use just use OVMF.fd with a single pflash device. libvirt recently got support for that. Just using -bios OVMF.fd might work too. Daniel tried that recently for sev, but ran into problems with wiring up ovmf metadata parsing for -bios. Don't remember the details though. take care, Gerd
On Mon, Mar 21, 2022 at 04:54:51PM +0800, Xiaoyao Li wrote: > On 3/18/2022 10:07 PM, Philippe Mathieu-Daudé wrote: > > Hi, > > > > On 17/3/22 14:58, Xiaoyao Li wrote: > > > TDX VM needs to boot with Trust Domain Virtual Firmware (TDVF). Unlike > > > that OVMF is mapped as rom device, TDVF needs to be mapped as private > > > memory. This is because TDX architecture doesn't provide read-only > > > capability for VMM, and it doesn't support instruction emulation due > > > to guest memory and registers are not accessible for VMM. > > > > > > On the other hand, OVMF can work as TDVF, which is usually configured > > > as pflash device in QEMU. To keep the same usage (QEMU parameter), > > > introduce ram_mode to pflash for TDVF. When it's creating a TDX VM, > > > ram_mode will be enabled automatically that map the firmware as RAM. > > > > > > Note, this implies two things: > > > 1. TDVF (OVMF) is not read-only (write-protected). > > > > > > 2. It doesn't support non-volatile UEFI variables as what pflash > > > supports that the change to non-volatile UEFI variables won't get > > > synced back to backend vars.fd file. > > > > > > Signed-off-by: Xiaoyao Li <xiaoyao.li@intel.com> > > > --- > > > hw/block/pflash_cfi01.c | 25 ++++++++++++++++++------- > > > hw/i386/pc_sysfw.c | 14 +++++++++++--- > > > 2 files changed, 29 insertions(+), 10 deletions(-) > > > > If you don't need a pflash device, don't use it: simply map your nvram > > region as ram in your machine. No need to clutter the pflash model like > > that. > > I know it's dirty to hack the pflash device. The purpose is to make the user > interface unchanged that people can still use > > -drive if=pflash,format=raw,unit=0,file=/path/to/OVMF_CODE.fd > -drive if=pflash,format=raw,unit=1,file=/path/to/OVMF_VARS.fd Note, that in the default pflash config, libvirt will set the 'readonly=on' flag for OVMF_CODE.fd ie, it will use -drive if=pflash,format=raw,unit=0,file=/path/to/OVMF_CODE.fd,readonly=on -drive if=pflash,format=raw,unit=1,file=/path/to/OVMF_VARS.fd IOW, we're requiring OVMF_CODE.fd is ROM, while OVMF_VARS.fd is NVRAM IIUC, this patch here is changing the semantics of these args: - OVMF_CODE.fd is mapped as RAM, but IIUC, QEMU would still be prevented from writing to it due to readonly=on in the block layer - OVMF_VARS.fd is mapped as RAM, but IIUC you're saying that none the less, any writes don't propagate back into the file ? Dealing with OVMF_VARS.fd first, I really wonder why you want to have a OVMF_VARS.fd file at all, if you don't have writes propagated into it ? It has no reason to exist if you're not writing to it. IMHO the AmdSev build for OVMF gets this right by entirely disabling the split OVMF_CODE.fd vs OVMF_VARS.fd, and just having a single OVMF.fd file that is exposed read-only to the guest. This is further represented in $QEMU.git/docs/interop/firmware.json by marking the firmware as 'stateless', which apps like libvirt will use to figure out what QEMU command line to pick. IOW, if you don't want OVMF_VARS.fd to be written to, then follow what AmdSev has done, and get rid of the split files. As for exposing OVMF_CODE.fd as RAM instead of ROM. That feels a little odd, but as long as its backing store file on disk honours the readony=on request to -drive, that's not terrible IMHO. With regards, Daniel
On Tue, Mar 22, 2022 at 10:21:41AM +0100, Gerd Hoffmann wrote: > Hi, > > > > If you don't need a pflash device, don't use it: simply map your nvram > > > region as ram in your machine. No need to clutter the pflash model like > > > that. > > Using the pflash device for something which isn't actually flash looks a > bit silly indeed. > > > > > I know it's dirty to hack the pflash device. The purpose is to make the user > > interface unchanged that people can still use > > > > -drive if=pflash,format=raw,unit=0,file=/path/to/OVMF_CODE.fd > > -drive if=pflash,format=raw,unit=1,file=/path/to/OVMF_VARS.fd > > > > to create TD guest. > > Well, if persistent vars are not supported anyway there is little reason > to split the firmware into CODE and VARS files. You can use just use > OVMF.fd with a single pflash device. libvirt recently got support for > that. Agreed. > Just using -bios OVMF.fd might work too. Daniel tried that recently for > sev, but ran into problems with wiring up ovmf metadata parsing for > -bios. Don't remember the details though. It was related to the BIOS shadowing, whereby QEMU loads it at one address, and then when CPUs start it is copied to another address. This was not compatible with the way AMD SEV wants to do measurement of the firmware. May or may not be relevant for TDX, I don't know enough about TDX to say. With regards, Daniel
Hi, > > Just using -bios OVMF.fd might work too. Daniel tried that recently for > > sev, but ran into problems with wiring up ovmf metadata parsing for > > -bios. Don't remember the details though. > > It was related to the BIOS shadowing, whereby QEMU loads it at one > address, and then when CPUs start it is copied to another address. Is this the top 128k of the firmware being copied below 1M so the firmware reset vector is available in real mode address space? > This was not compatible with the way AMD SEV wants to do measurement > of the firmware. May or may not be relevant for TDX, I don't know > enough about TDX to say. TDX boots in 32bit mode, so simply skipping any real mode compatibility stuff shouldn't cause any problems here. Not sure about SEV. There is this SevProcessorReset entry in the ovmf metadata block. Is that the SEV reset vector? If SEV cpu bringup doesn't go through real mode either we maybe can just skip the BIOS shadowing setup for confidential computing guests ... take care, Gerd
On Tue, Mar 22, 2022 at 11:35:18AM +0100, Gerd Hoffmann wrote: > Hi, > > > > Just using -bios OVMF.fd might work too. Daniel tried that recently for > > > sev, but ran into problems with wiring up ovmf metadata parsing for > > > -bios. Don't remember the details though. > > > > It was related to the BIOS shadowing, whereby QEMU loads it at one > > address, and then when CPUs start it is copied to another address. > > Is this the top 128k of the firmware being copied below 1M so the > firmware reset vector is available in real mode address space? It was the 'rom_reset' method in hw/core/loader.c that was involved in the root of the problem, copying the firmware from ROM to RAM. At the time I did try a gross hack that (IIRC) disabled the rom_reset logic, and munged x86_bios_rom_init so that it would force load it straight at the RAM location. I couldn't figure out an attractive way to make this into something supportable, so abandoned the whole idea. Messing with this area of code is a somewhat beyond my level of understanding of x86 boot process anyway. > > This was not compatible with the way AMD SEV wants to do measurement > > of the firmware. May or may not be relevant for TDX, I don't know > > enough about TDX to say. > > TDX boots in 32bit mode, so simply skipping any real mode compatibility > stuff shouldn't cause any problems here. > > Not sure about SEV. There is this SevProcessorReset entry in the ovmf > metadata block. Is that the SEV reset vector? If SEV cpu bringup > doesn't go through real mode either we maybe can just skip the BIOS > shadowing setup for confidential computing guests ... With regards, Daniel
Hi, > At the time I did try a gross hack that (IIRC) disabled the > rom_reset logic, and munged x86_bios_rom_init so that it would > force load it straight at the RAM location. Sounds reasonable. The whole rom logic exists to handle resets, but with confidential guests we don't need that, we can't change guest state to perform a reset anyway ... take care, Gerd diff --git a/hw/i386/x86.c b/hw/i386/x86.c index 4cf107baea34..169ef96682de 100644 --- a/hw/i386/x86.c +++ b/hw/i386/x86.c @@ -1115,15 +1115,26 @@ void x86_bios_rom_init(MachineState *ms, const char *default_firmware, goto bios_error; } bios = g_malloc(sizeof(*bios)); + memory_region_init_ram(bios, NULL, "pc.bios", bios_size, &error_fatal); - if (!isapc_ram_fw) { - memory_region_set_readonly(bios, true); - } - ret = rom_add_file_fixed(bios_name, (uint32_t)(-bios_size), -1); - if (ret != 0) { - bios_error: - fprintf(stderr, "qemu: could not load PC BIOS '%s'\n", bios_name); - exit(1); + if (1 /* confidential computing */) { + /* + * The concept of a "reset" simply doesn't exist for + * confidential computing guests, we have to destroy and + * re-launch them instead. So there is no need to register + * the firmware as rom to properly re-initialize on reset. + * Just go for a straight file load instead. + */ + void *ptr = memory_region_get_ram_ptr(bios); + load_image_size(filename, ptr, bios_size); + } else { + if (!isapc_ram_fw) { + memory_region_set_readonly(bios, true); + } + ret = rom_add_file_fixed(bios_name, (uint32_t)(-bios_size), -1); + if (ret != 0) { + goto bios_error; + } } g_free(filename); @@ -1144,6 +1155,11 @@ void x86_bios_rom_init(MachineState *ms, const char *default_firmware, memory_region_add_subregion(rom_memory, (uint32_t)(-bios_size), bios); + return; + +bios_error: + fprintf(stderr, "qemu: could not load PC BIOS '%s'\n", bios_name); + exit(1); } bool x86_machine_is_smm_enabled(const X86MachineState *x86ms)
On 3/22/2022 5:29 PM, Daniel P. Berrangé wrote: > On Tue, Mar 22, 2022 at 10:21:41AM +0100, Gerd Hoffmann wrote: >> Hi, >> >>>> If you don't need a pflash device, don't use it: simply map your nvram >>>> region as ram in your machine. No need to clutter the pflash model like >>>> that. >> >> Using the pflash device for something which isn't actually flash looks a >> bit silly indeed. >> >>> >>> I know it's dirty to hack the pflash device. The purpose is to make the user >>> interface unchanged that people can still use >>> >>> -drive if=pflash,format=raw,unit=0,file=/path/to/OVMF_CODE.fd >>> -drive if=pflash,format=raw,unit=1,file=/path/to/OVMF_VARS.fd >>> >>> to create TD guest. >> >> Well, if persistent vars are not supported anyway there is little reason >> to split the firmware into CODE and VARS files. You can use just use >> OVMF.fd with a single pflash device. libvirt recently got support for >> that. > > Agreed. The purpose of using split firmware is that people can share the same code.fd while using different vars.fd
Hi, > > > Well, if persistent vars are not supported anyway there is little reason > > > to split the firmware into CODE and VARS files. You can use just use > > > OVMF.fd with a single pflash device. libvirt recently got support for > > > that. > > > > Agreed. > > The purpose of using split firmware is that people can share the same > code.fd while using different vars.fd Using different vars.fd files is pointless though when changes are never written back ... take care, Gerd
On 3/24/2022 3:58 PM, Gerd Hoffmann wrote: > Hi, > >>>> Well, if persistent vars are not supported anyway there is little reason >>>> to split the firmware into CODE and VARS files. You can use just use >>>> OVMF.fd with a single pflash device. libvirt recently got support for >>>> that. >>> >>> Agreed. >> >> The purpose of using split firmware is that people can share the same >> code.fd while using different vars.fd > > Using different vars.fd files is pointless though when changes are never > written back ... Yes, I agree on this. Off the topic. If we really want to NVRAM capability to TDX guest, 1) we can use the PV interface issue MMIO write in OVMF, like what SEV does in OVMF. 2) map OVMF as shared, thus existing pflash works well. However, both options will expose the content to VMM, which loses confidentiality. > take care, > Gerd >
On Tue, Mar 22, 2022 at 01:20:24PM +0100, Gerd Hoffmann wrote: > Hi, > > > At the time I did try a gross hack that (IIRC) disabled the > > rom_reset logic, and munged x86_bios_rom_init so that it would > > force load it straight at the RAM location. > > Sounds reasonable. The whole rom logic exists to handle resets, > but with confidential guests we don't need that, we can't change > guest state to perform a reset anyway ... Completed, cleaned up a bit, but untested: https://git.kraxel.org/cgit/qemu/log/?h=sirius/cc Any chance you can give this a try? thanks, Gerd
On Thu, Mar 24, 2022 at 02:13:53PM +0800, Xiaoyao Li wrote: > On 3/22/2022 5:29 PM, Daniel P. Berrangé wrote: > > On Tue, Mar 22, 2022 at 10:21:41AM +0100, Gerd Hoffmann wrote: > > > Hi, > > > > > > > > If you don't need a pflash device, don't use it: simply map your nvram > > > > > region as ram in your machine. No need to clutter the pflash model like > > > > > that. > > > > > > Using the pflash device for something which isn't actually flash looks a > > > bit silly indeed. > > > > > > > > > > > I know it's dirty to hack the pflash device. The purpose is to make the user > > > > interface unchanged that people can still use > > > > > > > > -drive if=pflash,format=raw,unit=0,file=/path/to/OVMF_CODE.fd > > > > -drive if=pflash,format=raw,unit=1,file=/path/to/OVMF_VARS.fd > > > > > > > > to create TD guest. > > > > > > Well, if persistent vars are not supported anyway there is little reason > > > to split the firmware into CODE and VARS files. You can use just use > > > OVMF.fd with a single pflash device. libvirt recently got support for > > > that. > > > > Agreed. > > The purpose of using split firmware is that people can share the same > code.fd while using different vars.fd That's fine for firmware that writes to vars.fd, but it was said earlier that changes aren't written with TDX (nor are they written with SEV), so a separate vars.fd serves no pupose in these cases. With regards, Daniel
On 3/24/2022 4:35 PM, Gerd Hoffmann wrote: > On Tue, Mar 22, 2022 at 01:20:24PM +0100, Gerd Hoffmann wrote: >> Hi, >> >>> At the time I did try a gross hack that (IIRC) disabled the >>> rom_reset logic, and munged x86_bios_rom_init so that it would >>> force load it straight at the RAM location. >> >> Sounds reasonable. The whole rom logic exists to handle resets, >> but with confidential guests we don't need that, we can't change >> guest state to perform a reset anyway ... > > Completed, cleaned up a bit, but untested: > https://git.kraxel.org/cgit/qemu/log/?h=sirius/cc > > Any chance you can give this a try? Hi Gred, I refactor the TDX series to load TDVF via "-bios" option upon it. No issue hit. Thanks, -Xiaoyao > thanks, > Gerd >
On 3/22/2022 5:27 PM, Daniel P. Berrangé wrote: ... > IMHO the AmdSev build for OVMF gets this right by entirely disabling > the split OVMF_CODE.fd vs OVMF_VARS.fd, and just having a single > OVMF.fd file that is exposed read-only to the guest. > > This is further represented in $QEMU.git/docs/interop/firmware.json > by marking the firmware as 'stateless', which apps like libvirt will > use to figure out what QEMU command line to pick. Hi Daniel, I don't play with AMD SEV and I'm not sure if AMD SEV requires only single OVMF.fd. But IIUC, from edk2 commit 437eb3f7a8db ("OvmfPkg/QemuFlashFvbServicesRuntimeDxe: Bypass flash detection with SEV-ES") , AMD SEV(-ES) does support NVRAM via proactive VMGEXIT MMIO QemuFlashWrite(). If so, AMD SEV seems to be able to support split OVMF, right? > IOW, if you don't want OVMF_VARS.fd to be written to, then follow > what AmdSev has done, and get rid of the split files. > > > With regards, > Daniel
On Thu, Mar 31, 2022 at 04:51:27PM +0800, Xiaoyao Li wrote: > On 3/22/2022 5:27 PM, Daniel P. Berrangé wrote: > ... > > IMHO the AmdSev build for OVMF gets this right by entirely disabling > > the split OVMF_CODE.fd vs OVMF_VARS.fd, and just having a single > > OVMF.fd file that is exposed read-only to the guest. > > > > This is further represented in $QEMU.git/docs/interop/firmware.json > > by marking the firmware as 'stateless', which apps like libvirt will > > use to figure out what QEMU command line to pick. > > Hi Daniel, > > I don't play with AMD SEV and I'm not sure if AMD SEV requires only single > OVMF.fd. But IIUC, from edk2 > > commit 437eb3f7a8db ("OvmfPkg/QemuFlashFvbServicesRuntimeDxe: Bypass flash > detection with SEV-ES") > > , AMD SEV(-ES) does support NVRAM via proactive VMGEXIT MMIO > QemuFlashWrite(). If so, AMD SEV seems to be able to support split OVMF, > right? Note that while the traditional OvmfPkg build can be used with SEV/SEV-ES, this is not viable for measured boot, as it uses the NVRAM whose content is not measured. I was specifically referring to the OvmfPkg/AmdSev build which doesn't use seprate NVRAM, and has no variables persistence. With regards, Daniel
On 3/31/2022 5:00 PM, Daniel P. Berrangé wrote: > On Thu, Mar 31, 2022 at 04:51:27PM +0800, Xiaoyao Li wrote: >> On 3/22/2022 5:27 PM, Daniel P. Berrangé wrote: >> ... >>> IMHO the AmdSev build for OVMF gets this right by entirely disabling >>> the split OVMF_CODE.fd vs OVMF_VARS.fd, and just having a single >>> OVMF.fd file that is exposed read-only to the guest. >>> >>> This is further represented in $QEMU.git/docs/interop/firmware.json >>> by marking the firmware as 'stateless', which apps like libvirt will >>> use to figure out what QEMU command line to pick. >> >> Hi Daniel, >> >> I don't play with AMD SEV and I'm not sure if AMD SEV requires only single >> OVMF.fd. But IIUC, from edk2 >> >> commit 437eb3f7a8db ("OvmfPkg/QemuFlashFvbServicesRuntimeDxe: Bypass flash >> detection with SEV-ES") >> >> , AMD SEV(-ES) does support NVRAM via proactive VMGEXIT MMIO >> QemuFlashWrite(). If so, AMD SEV seems to be able to support split OVMF, >> right? > > Note that while the traditional OvmfPkg build can be used with > SEV/SEV-ES, this is not viable for measured boot, as it uses > the NVRAM whose content is not measured. > > I was specifically referring to the OvmfPkg/AmdSev build which > doesn't use seprate NVRAM, and has no variables persistence. Thanks for the info. It seems I need to learn more about those. It would be very appreciated if you can provide me some links. > With regards, > Daniel
diff --git a/hw/block/pflash_cfi01.c b/hw/block/pflash_cfi01.c index 74c7190302bd..55e8bb2bd5ee 100644 --- a/hw/block/pflash_cfi01.c +++ b/hw/block/pflash_cfi01.c @@ -87,6 +87,7 @@ struct PFlashCFI01 { void *storage; VMChangeStateEntry *vmstate; bool old_multiple_chip_handling; + bool ram_mode; /* if 1, the flash is mapped as RAM */ }; static int pflash_post_load(void *opaque, int version_id); @@ -818,17 +819,24 @@ static void pflash_cfi01_realize(DeviceState *dev, Error **errp) total_len = pfl->sector_len * pfl->nb_blocs; - memory_region_init_rom_device( - &pfl->mem, OBJECT(dev), - &pflash_cfi01_ops, - pfl, - pfl->name, total_len, errp); + if (pfl->ram_mode) { + memory_region_init_ram(&pfl->mem, OBJECT(dev),pfl->name, total_len, errp); + } else { + memory_region_init_rom_device( + &pfl->mem, OBJECT(dev), + &pflash_cfi01_ops, + pfl, + pfl->name, total_len, errp); + } if (*errp) { return; } pfl->storage = memory_region_get_ram_ptr(&pfl->mem); - sysbus_init_mmio(SYS_BUS_DEVICE(dev), &pfl->mem); + + if (!pfl->ram_mode) { + sysbus_init_mmio(SYS_BUS_DEVICE(dev), &pfl->mem); + } if (pfl->blk) { uint64_t perm; @@ -879,7 +887,9 @@ static void pflash_cfi01_system_reset(DeviceState *dev) */ pfl->cmd = 0x00; pfl->wcycle = 0; - memory_region_rom_device_set_romd(&pfl->mem, true); + if (!pfl->ram_mode) { + memory_region_rom_device_set_romd(&pfl->mem, true); + } /* * The WSM ready timer occurs at most 150ns after system reset. * This model deliberately ignores this delay. @@ -924,6 +934,7 @@ static Property pflash_cfi01_properties[] = { DEFINE_PROP_STRING("name", PFlashCFI01, name), DEFINE_PROP_BOOL("old-multiple-chip-handling", PFlashCFI01, old_multiple_chip_handling, false), + DEFINE_PROP_BOOL("ram-mode", PFlashCFI01, ram_mode, false), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/i386/pc_sysfw.c b/hw/i386/pc_sysfw.c index 75b34d02cb4f..03c84b5aaa32 100644 --- a/hw/i386/pc_sysfw.c +++ b/hw/i386/pc_sysfw.c @@ -38,6 +38,7 @@ #include "hw/block/flash.h" #include "sysemu/kvm.h" #include "sev.h" +#include "kvm/tdx.h" #define FLASH_SECTOR_SIZE 4096 @@ -184,12 +185,19 @@ static void pc_system_flash_map(PCMachineState *pcms, total_size += size; qdev_prop_set_uint32(DEVICE(system_flash), "num-blocks", size / FLASH_SECTOR_SIZE); + qdev_prop_set_bit(DEVICE(system_flash), "ram-mode", is_tdx_vm()); sysbus_realize_and_unref(SYS_BUS_DEVICE(system_flash), &error_fatal); - sysbus_mmio_map(SYS_BUS_DEVICE(system_flash), 0, - 0x100000000ULL - total_size); + flash_mem = pflash_cfi01_get_memory(system_flash); + if (is_tdx_vm()) { + memory_region_add_subregion(get_system_memory(), + 0x100000000ULL - total_size, + flash_mem); + } else { + sysbus_mmio_map(SYS_BUS_DEVICE(system_flash), 0, + 0x100000000ULL - total_size); + } if (i == 0) { - flash_mem = pflash_cfi01_get_memory(system_flash); pc_isa_bios_init(rom_memory, flash_mem, size); /* Encrypt the pflash boot ROM */
TDX VM needs to boot with Trust Domain Virtual Firmware (TDVF). Unlike that OVMF is mapped as rom device, TDVF needs to be mapped as private memory. This is because TDX architecture doesn't provide read-only capability for VMM, and it doesn't support instruction emulation due to guest memory and registers are not accessible for VMM. On the other hand, OVMF can work as TDVF, which is usually configured as pflash device in QEMU. To keep the same usage (QEMU parameter), introduce ram_mode to pflash for TDVF. When it's creating a TDX VM, ram_mode will be enabled automatically that map the firmware as RAM. Note, this implies two things: 1. TDVF (OVMF) is not read-only (write-protected). 2. It doesn't support non-volatile UEFI variables as what pflash supports that the change to non-volatile UEFI variables won't get synced back to backend vars.fd file. Signed-off-by: Xiaoyao Li <xiaoyao.li@intel.com> --- hw/block/pflash_cfi01.c | 25 ++++++++++++++++++------- hw/i386/pc_sysfw.c | 14 +++++++++++--- 2 files changed, 29 insertions(+), 10 deletions(-)