summaryrefslogtreecommitdiffstats
path: root/hw/i386/x86.c
diff options
context:
space:
mode:
authorStefan Hajnoczi2022-10-04 20:03:21 +0200
committerStefan Hajnoczi2022-10-04 20:03:21 +0200
commitf8ec554cb87503806ca341b69d3474c8cfdf6c28 (patch)
treefa0d73c20e87cb3a38168036a841ccc9a077bf39 /hw/i386/x86.c
parentMerge tag 'for-upstream' of git://repo.or.cz/qemu/kevin into staging (diff)
parentx86: re-initialize RNG seed when selecting kernel (diff)
downloadqemu-f8ec554cb87503806ca341b69d3474c8cfdf6c28.tar.gz
qemu-f8ec554cb87503806ca341b69d3474c8cfdf6c28.tar.xz
qemu-f8ec554cb87503806ca341b69d3474c8cfdf6c28.zip
Merge tag 'for-upstream' of https://gitlab.com/bonzini/qemu into staging
* x86: re-enable rng seeding via SetupData * x86: reinitialize RNG seed on system reboot and after kernel load * qboot: rebuild based on latest commit * watchdog: remove -watchdog option * update Meson to 0.61.5, move more configure tests # -----BEGIN PGP SIGNATURE----- # # iQFIBAABCAAyFiEE8TM4V0tmI4mGbHaCv/vSX3jHroMFAmM4kiAUHHBib256aW5p # QHJlZGhhdC5jb20ACgkQv/vSX3jHroNfbgf+IHhIHVxtBVWqayVRkwpQC+oAFV/V # 4bvJI90rHmTNPA36n1ocUmQmXyNVTQFW/t7mlln5BhOwNzxnQycVe2idfMa6ntkb # hHpe2NbICF9Crzb9BkK4wnaBLwEWA/X3WlnCqPYtxlxEhjmxu+HPtF7vm12OTkOV # JevH3EN1gMiAfMo+gcRBlrwb5kntLm3nGZTCd218Ope22PoU6MVvxb9ivieJG8kD # xDUGPQNU0mB9pypwLYZAqmu34xJ8Stly9UuJ1M2iQoawIs7W2Qy7svpOrsKZ3W/7 # D7J18QLAjI7Hq6rUWPgK5ugnUvVMdaTXM7MZSuIDIxRJuj5YryIsHRPybQ== # =HEmX # -----END PGP SIGNATURE----- # gpg: Signature made Sat 01 Oct 2022 15:16:48 EDT # gpg: using RSA key F13338574B662389866C7682BFFBD25F78C7AE83 # gpg: issuer "pbonzini@redhat.com" # gpg: Good signature from "Paolo Bonzini <bonzini@gnu.org>" [full] # gpg: aka "Paolo Bonzini <pbonzini@redhat.com>" [full] # Primary key fingerprint: 46F5 9FBD 57D6 12E7 BFD4 E2F7 7E15 100C CD36 69B1 # Subkey fingerprint: F133 3857 4B66 2389 866C 7682 BFFB D25F 78C7 AE83 * tag 'for-upstream' of https://gitlab.com/bonzini/qemu: x86: re-initialize RNG seed when selecting kernel target/i386/kvm: fix kvmclock_current_nsec: Assertion `time.tsc_timestamp <= migration_tsc' failed configure, meson: move linker flag detection to meson configure, meson: move C++ compiler detection to meson.build meson: multiple names can be passed to dependency() meson: require 0.61.3 meson: -display dbus and CFI are incompatible ui: fix path to dbus-display1.h watchdog: remove -watchdog option configure: do not invoke as/ld directly for pc-bios/optionrom qboot: rebuild based on latest commit x86: re-enable rng seeding via SetupData x86: reinitialize RNG seed on system reboot x86: use typedef for SetupData struct x86: return modified setup_data only if read as memory, not as file Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Diffstat (limited to 'hw/i386/x86.c')
-rw-r--r--hw/i386/x86.c70
1 files changed, 53 insertions, 17 deletions
diff --git a/hw/i386/x86.c b/hw/i386/x86.c
index 050eedc0c8..1148f70c03 100644
--- a/hw/i386/x86.c
+++ b/hw/i386/x86.c
@@ -37,6 +37,7 @@
#include "sysemu/whpx.h"
#include "sysemu/numa.h"
#include "sysemu/replay.h"
+#include "sysemu/reset.h"
#include "sysemu/sysemu.h"
#include "sysemu/cpu-timers.h"
#include "sysemu/xen.h"
@@ -652,12 +653,12 @@ DeviceState *ioapic_init_secondary(GSIState *gsi_state)
return dev;
}
-struct setup_data {
+typedef struct SetupData {
uint64_t next;
uint32_t type;
uint32_t len;
uint8_t data[];
-} __attribute__((packed));
+} __attribute__((packed)) SetupData;
/*
@@ -764,6 +765,30 @@ static bool load_elfboot(const char *kernel_filename,
return true;
}
+typedef struct SetupDataFixup {
+ void *pos;
+ hwaddr orig_val, new_val;
+ uint32_t addr;
+} SetupDataFixup;
+
+static void fixup_setup_data(void *opaque)
+{
+ SetupDataFixup *fixup = opaque;
+ stq_p(fixup->pos, fixup->new_val);
+}
+
+static void reset_setup_data(void *opaque)
+{
+ SetupDataFixup *fixup = opaque;
+ stq_p(fixup->pos, fixup->orig_val);
+}
+
+static void reset_rng_seed(void *opaque)
+{
+ SetupData *setup_data = opaque;
+ qemu_guest_getrandom_nofail(setup_data->data, le32_to_cpu(setup_data->len));
+}
+
void x86_load_linux(X86MachineState *x86ms,
FWCfgState *fw_cfg,
int acpi_data_size,
@@ -780,7 +805,7 @@ void x86_load_linux(X86MachineState *x86ms,
FILE *f;
char *vmode;
MachineState *machine = MACHINE(x86ms);
- struct setup_data *setup_data;
+ SetupData *setup_data;
const char *kernel_filename = machine->kernel_filename;
const char *initrd_filename = machine->initrd_filename;
const char *dtb_filename = machine->dtb;
@@ -1063,11 +1088,11 @@ void x86_load_linux(X86MachineState *x86ms,
}
setup_data_offset = QEMU_ALIGN_UP(kernel_size, 16);
- kernel_size = setup_data_offset + sizeof(struct setup_data) + dtb_size;
+ kernel_size = setup_data_offset + sizeof(SetupData) + dtb_size;
kernel = g_realloc(kernel, kernel_size);
- setup_data = (struct setup_data *)(kernel + setup_data_offset);
+ setup_data = (SetupData *)(kernel + setup_data_offset);
setup_data->next = cpu_to_le64(first_setup_data);
first_setup_data = prot_addr + setup_data_offset;
setup_data->type = cpu_to_le32(SETUP_DTB);
@@ -1078,18 +1103,25 @@ void x86_load_linux(X86MachineState *x86ms,
if (!legacy_no_rng_seed) {
setup_data_offset = QEMU_ALIGN_UP(kernel_size, 16);
- kernel_size = setup_data_offset + sizeof(struct setup_data) + RNG_SEED_LENGTH;
+ kernel_size = setup_data_offset + sizeof(SetupData) + RNG_SEED_LENGTH;
kernel = g_realloc(kernel, kernel_size);
- setup_data = (struct setup_data *)(kernel + setup_data_offset);
+ setup_data = (SetupData *)(kernel + setup_data_offset);
setup_data->next = cpu_to_le64(first_setup_data);
first_setup_data = prot_addr + setup_data_offset;
setup_data->type = cpu_to_le32(SETUP_RNG_SEED);
setup_data->len = cpu_to_le32(RNG_SEED_LENGTH);
qemu_guest_getrandom_nofail(setup_data->data, RNG_SEED_LENGTH);
+ qemu_register_reset(reset_rng_seed, setup_data);
+ fw_cfg_add_bytes_callback(fw_cfg, FW_CFG_KERNEL_DATA, reset_rng_seed, NULL,
+ setup_data, kernel, kernel_size, true);
+ } else {
+ fw_cfg_add_bytes(fw_cfg, FW_CFG_KERNEL_DATA, kernel, kernel_size);
}
- /* Offset 0x250 is a pointer to the first setup_data link. */
- stq_p(header + 0x250, first_setup_data);
+ fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, prot_addr);
+ fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_SIZE, kernel_size);
+ sev_load_ctx.kernel_data = (char *)kernel;
+ sev_load_ctx.kernel_size = kernel_size;
/*
* If we're starting an encrypted VM, it will be OVMF based, which uses the
@@ -1099,16 +1131,20 @@ void x86_load_linux(X86MachineState *x86ms,
* file the user passed in.
*/
if (!sev_enabled()) {
+ SetupDataFixup *fixup = g_malloc(sizeof(*fixup));
+
memcpy(setup, header, MIN(sizeof(header), setup_size));
+ /* Offset 0x250 is a pointer to the first setup_data link. */
+ fixup->pos = setup + 0x250;
+ fixup->orig_val = ldq_p(fixup->pos);
+ fixup->new_val = first_setup_data;
+ fixup->addr = cpu_to_le32(real_addr);
+ fw_cfg_add_bytes_callback(fw_cfg, FW_CFG_SETUP_ADDR, fixup_setup_data, NULL,
+ fixup, &fixup->addr, sizeof(fixup->addr), true);
+ qemu_register_reset(reset_setup_data, fixup);
+ } else {
+ fw_cfg_add_i32(fw_cfg, FW_CFG_SETUP_ADDR, real_addr);
}
-
- fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, prot_addr);
- fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_SIZE, kernel_size);
- fw_cfg_add_bytes(fw_cfg, FW_CFG_KERNEL_DATA, kernel, kernel_size);
- sev_load_ctx.kernel_data = (char *)kernel;
- sev_load_ctx.kernel_size = kernel_size;
-
- fw_cfg_add_i32(fw_cfg, FW_CFG_SETUP_ADDR, real_addr);
fw_cfg_add_i32(fw_cfg, FW_CFG_SETUP_SIZE, setup_size);
fw_cfg_add_bytes(fw_cfg, FW_CFG_SETUP_DATA, setup, setup_size);
sev_load_ctx.setup_data = (char *)setup;