[PATCH v2 11/32] kvm/i386: reload firmware for confidential guest reset

Ani Sinha posted 32 patches 4 weeks ago
[PATCH v2 11/32] kvm/i386: reload firmware for confidential guest reset
Posted by Ani Sinha 4 weeks ago
When IGVM is not being used by the confidential guest, the guest firmware has
to be reloaded explictly again into memory. This is because, the memory into
which the firmware was loaded before reset was encrypted and is thus lost
upon reset. When IGVM is used, it is expected that the IGVM will contain the
guest firmware and the execution of the IGVM directives will set up the guest
firmware memory.

Signed-off-by: Ani Sinha <anisinha@redhat.com>
---
 target/i386/kvm/kvm.c | 28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)

diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c
index 4fedc621b8..46c4f9487b 100644
--- a/target/i386/kvm/kvm.c
+++ b/target/i386/kvm/kvm.c
@@ -51,6 +51,8 @@
 #include "qemu/config-file.h"
 #include "qemu/error-report.h"
 #include "qemu/memalign.h"
+#include "qemu/datadir.h"
+#include "hw/core/loader.h"
 #include "hw/i386/x86.h"
 #include "hw/i386/kvm/xen_evtchn.h"
 #include "hw/i386/pc.h"
@@ -3267,6 +3269,22 @@ static int kvm_vm_enable_energy_msrs(KVMState *s)
 
 static int xen_init_wrapper(MachineState *ms, KVMState *s);
 
+static void reload_bios_rom(X86MachineState *x86ms)
+{
+    int bios_size;
+    const char *bios_name;
+    char *filename;
+
+    bios_name = MACHINE(x86ms)->firmware ?: "bios.bin";
+    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
+
+    bios_size = get_bios_size(x86ms, bios_name, filename);
+
+    void *ptr = memory_region_get_ram_ptr(&x86ms->bios);
+    load_image_size(filename, ptr, bios_size);
+    x86_firmware_configure(0x100000000ULL - bios_size, ptr, bios_size);
+}
+
 int kvm_arch_vmfd_change_ops(MachineState *ms, KVMState *s)
 {
     Error *local_err = NULL;
@@ -3285,6 +3303,16 @@ int kvm_arch_vmfd_change_ops(MachineState *ms, KVMState *s)
             error_report_err(local_err);
             return ret;
         }
+        if (object_dynamic_cast(OBJECT(ms), TYPE_X86_MACHINE)) {
+            X86MachineState *x86ms = X86_MACHINE(ms);
+            /*
+             * If an IGVM file is specified then the firmware must be provided
+             * in the IGVM file.
+             */
+            if (!x86ms->igvm) {
+                reload_bios_rom(x86ms);
+            }
+        }
     }
 
     ret = kvm_vm_enable_exception_payload(s);
-- 
2.42.0
Re: [PATCH v2 11/32] kvm/i386: reload firmware for confidential guest reset
Posted by Bernhard Beschow 3 weeks, 6 days ago

Am 12. Januar 2026 13:22:24 UTC schrieb Ani Sinha <anisinha@redhat.com>:
>When IGVM is not being used by the confidential guest, the guest firmware has
>to be reloaded explictly again into memory. This is because, the memory into
>which the firmware was loaded before reset was encrypted and is thus lost
>upon reset. When IGVM is used, it is expected that the IGVM will contain the
>guest firmware and the execution of the IGVM directives will set up the guest
>firmware memory.
>
>Signed-off-by: Ani Sinha <anisinha@redhat.com>
>---
> target/i386/kvm/kvm.c | 28 ++++++++++++++++++++++++++++
> 1 file changed, 28 insertions(+)
>
>diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c
>index 4fedc621b8..46c4f9487b 100644
>--- a/target/i386/kvm/kvm.c
>+++ b/target/i386/kvm/kvm.c
>@@ -51,6 +51,8 @@
> #include "qemu/config-file.h"
> #include "qemu/error-report.h"
> #include "qemu/memalign.h"
>+#include "qemu/datadir.h"
>+#include "hw/core/loader.h"
> #include "hw/i386/x86.h"
> #include "hw/i386/kvm/xen_evtchn.h"
> #include "hw/i386/pc.h"
>@@ -3267,6 +3269,22 @@ static int kvm_vm_enable_energy_msrs(KVMState *s)
> 
> static int xen_init_wrapper(MachineState *ms, KVMState *s);
> 
>+static void reload_bios_rom(X86MachineState *x86ms)
>+{
>+    int bios_size;
>+    const char *bios_name;
>+    char *filename;
>+
>+    bios_name = MACHINE(x86ms)->firmware ?: "bios.bin";
>+    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
>+
>+    bios_size = get_bios_size(x86ms, bios_name, filename);
>+
>+    void *ptr = memory_region_get_ram_ptr(&x86ms->bios);
>+    load_image_size(filename, ptr, bios_size);
>+    x86_firmware_configure(0x100000000ULL - bios_size, ptr, bios_size);
>+}

All code in this function is already present in x86-common.c. Can we move this function there (possibly renaming it to x86_bios_rom_reload()) and export it? This way, we could avoid code duplication and we didn't need to export additional functions like in the previous patch.

Best regards,
Bernhard

>+
> int kvm_arch_vmfd_change_ops(MachineState *ms, KVMState *s)
> {
>     Error *local_err = NULL;
>@@ -3285,6 +3303,16 @@ int kvm_arch_vmfd_change_ops(MachineState *ms, KVMState *s)
>             error_report_err(local_err);
>             return ret;
>         }
>+        if (object_dynamic_cast(OBJECT(ms), TYPE_X86_MACHINE)) {
>+            X86MachineState *x86ms = X86_MACHINE(ms);
>+            /*
>+             * If an IGVM file is specified then the firmware must be provided
>+             * in the IGVM file.
>+             */
>+            if (!x86ms->igvm) {
>+                reload_bios_rom(x86ms);
>+            }
>+        }
>     }
> 
>     ret = kvm_vm_enable_exception_payload(s);
Re: [PATCH v2 11/32] kvm/i386: reload firmware for confidential guest reset
Posted by Paolo Bonzini 4 weeks ago
On Mon, Jan 12, 2026 at 2:24 PM Ani Sinha <anisinha@redhat.com> wrote:
>
> When IGVM is not being used by the confidential guest, the guest firmware has
> to be reloaded explictly again into memory. This is because, the memory into
> which the firmware was loaded before reset was encrypted and is thus lost
> upon reset. When IGVM is used, it is expected that the IGVM will contain the
> guest firmware and the execution of the IGVM directives will set up the guest
> firmware memory.
>
> Signed-off-by: Ani Sinha <anisinha@redhat.com>
> ---
>  target/i386/kvm/kvm.c | 28 ++++++++++++++++++++++++++++
>  1 file changed, 28 insertions(+)
>
> diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c
> index 4fedc621b8..46c4f9487b 100644
> --- a/target/i386/kvm/kvm.c
> +++ b/target/i386/kvm/kvm.c
> @@ -51,6 +51,8 @@
>  #include "qemu/config-file.h"
>  #include "qemu/error-report.h"
>  #include "qemu/memalign.h"
> +#include "qemu/datadir.h"
> +#include "hw/core/loader.h"
>  #include "hw/i386/x86.h"
>  #include "hw/i386/kvm/xen_evtchn.h"
>  #include "hw/i386/pc.h"
> @@ -3267,6 +3269,22 @@ static int kvm_vm_enable_energy_msrs(KVMState *s)
>
>  static int xen_init_wrapper(MachineState *ms, KVMState *s);
>
> +static void reload_bios_rom(X86MachineState *x86ms)
> +{
> +    int bios_size;
> +    const char *bios_name;
> +    char *filename;
> +
> +    bios_name = MACHINE(x86ms)->firmware ?: "bios.bin";
> +    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
> +
> +    bios_size = get_bios_size(x86ms, bios_name, filename);
> +
> +    void *ptr = memory_region_get_ram_ptr(&x86ms->bios);
> +    load_image_size(filename, ptr, bios_size);
> +    x86_firmware_configure(0x100000000ULL - bios_size, ptr, bios_size);
> +}
> +
>  int kvm_arch_vmfd_change_ops(MachineState *ms, KVMState *s)
>  {
>      Error *local_err = NULL;
> @@ -3285,6 +3303,16 @@ int kvm_arch_vmfd_change_ops(MachineState *ms, KVMState *s)
>              error_report_err(local_err);
>              return ret;
>          }
> +        if (object_dynamic_cast(OBJECT(ms), TYPE_X86_MACHINE)) {
> +            X86MachineState *x86ms = X86_MACHINE(ms);
> +            /*
> +             * If an IGVM file is specified then the firmware must be provided
> +             * in the IGVM file.
> +             */
> +            if (!x86ms->igvm) {
> +                reload_bios_rom(x86ms);
> +            }
> +        }

Does this have to be done here, as opposed to in its own notifier or
anyway a notifier owned by the machine?

In any case, this can be done after the part in common with kvm_arch_init().

Paolo