x86.c (7f5acfcb662d32a736d0db41211cc7f340193bdd) x86.c (eac7a7791bb6d719233deed750034042318ffd56)
1/*
2 * Copyright (c) 2003-2004 Fabrice Bellard
3 * Copyright (c) 2019 Red Hat, Inc.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to deal
7 * in the Software without restriction, including without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell

--- 36 unchanged lines hidden (view full) ---

45
46#include "hw/i386/x86.h"
47#include "target/i386/cpu.h"
48#include "hw/i386/topology.h"
49#include "hw/i386/fw_cfg.h"
50#include "hw/intc/i8259.h"
51#include "hw/rtc/mc146818rtc.h"
52#include "target/i386/sev.h"
1/*
2 * Copyright (c) 2003-2004 Fabrice Bellard
3 * Copyright (c) 2019 Red Hat, Inc.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to deal
7 * in the Software without restriction, including without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell

--- 36 unchanged lines hidden (view full) ---

45
46#include "hw/i386/x86.h"
47#include "target/i386/cpu.h"
48#include "hw/i386/topology.h"
49#include "hw/i386/fw_cfg.h"
50#include "hw/intc/i8259.h"
51#include "hw/rtc/mc146818rtc.h"
52#include "target/i386/sev.h"
53#include "hw/i386/microvm.h"
53
54#include "hw/acpi/cpu_hotplug.h"
55#include "hw/irq.h"
56#include "hw/nmi.h"
57#include "hw/loader.h"
58#include "multiboot.h"
59#include "elf.h"
60#include "standard-headers/asm-x86/bootparam.h"

--- 747 unchanged lines hidden (view full) ---

808 hwaddr real_addr, prot_addr, cmdline_addr, initrd_addr = 0, first_setup_data = 0;
809 FILE *f;
810 char *vmode;
811 MachineState *machine = MACHINE(x86ms);
812 SetupData *setup_data;
813 const char *kernel_filename = machine->kernel_filename;
814 const char *initrd_filename = machine->initrd_filename;
815 const char *dtb_filename = machine->dtb;
54
55#include "hw/acpi/cpu_hotplug.h"
56#include "hw/irq.h"
57#include "hw/nmi.h"
58#include "hw/loader.h"
59#include "multiboot.h"
60#include "elf.h"
61#include "standard-headers/asm-x86/bootparam.h"

--- 747 unchanged lines hidden (view full) ---

809 hwaddr real_addr, prot_addr, cmdline_addr, initrd_addr = 0, first_setup_data = 0;
810 FILE *f;
811 char *vmode;
812 MachineState *machine = MACHINE(x86ms);
813 SetupData *setup_data;
814 const char *kernel_filename = machine->kernel_filename;
815 const char *initrd_filename = machine->initrd_filename;
816 const char *dtb_filename = machine->dtb;
816 const char *kernel_cmdline = machine->kernel_cmdline;
817 char *kernel_cmdline;
817 SevKernelLoaderContext sev_load_ctx = {};
818 enum { RNG_SEED_LENGTH = 32 };
819
818 SevKernelLoaderContext sev_load_ctx = {};
819 enum { RNG_SEED_LENGTH = 32 };
820
820 /* Align to 16 bytes as a paranoia measure */
821 cmdline_size = (strlen(kernel_cmdline) + 16) & ~15;
821 /*
822 * Add the NUL terminator, some padding for the microvm cmdline fiddling
823 * hack, and then align to 16 bytes as a paranoia measure
824 */
825 cmdline_size = (strlen(machine->kernel_cmdline) + 1 +
826 VIRTIO_CMDLINE_TOTAL_MAX_LEN + 16) & ~15;
827 /* Make a copy, since we might append arbitrary bytes to it later. */
828 kernel_cmdline = g_strndup(machine->kernel_cmdline, cmdline_size);
822
823 /* load the kernel header */
824 f = fopen(kernel_filename, "rb");
825 if (!f) {
826 fprintf(stderr, "qemu: could not open kernel file '%s': %s\n",
827 kernel_filename, strerror(errno));
828 exit(1);
829 }

--- 124 unchanged lines hidden (view full) ---

954 } else {
955 initrd_max = 0x37ffffff;
956 }
957
958 if (initrd_max >= x86ms->below_4g_mem_size - acpi_data_size) {
959 initrd_max = x86ms->below_4g_mem_size - acpi_data_size - 1;
960 }
961
829
830 /* load the kernel header */
831 f = fopen(kernel_filename, "rb");
832 if (!f) {
833 fprintf(stderr, "qemu: could not open kernel file '%s': %s\n",
834 kernel_filename, strerror(errno));
835 exit(1);
836 }

--- 124 unchanged lines hidden (view full) ---

961 } else {
962 initrd_max = 0x37ffffff;
963 }
964
965 if (initrd_max >= x86ms->below_4g_mem_size - acpi_data_size) {
966 initrd_max = x86ms->below_4g_mem_size - acpi_data_size - 1;
967 }
968
962 fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_ADDR, cmdline_addr);
963 fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_SIZE, strlen(kernel_cmdline) + 1);
964 fw_cfg_add_string(fw_cfg, FW_CFG_CMDLINE_DATA, kernel_cmdline);
965 sev_load_ctx.cmdline_data = (char *)kernel_cmdline;
966 sev_load_ctx.cmdline_size = strlen(kernel_cmdline) + 1;
967
968 if (protocol >= 0x202) {
969 stl_p(header + 0x228, cmdline_addr);
970 } else {
971 stw_p(header + 0x20, 0xA33F);
972 stw_p(header + 0x22, cmdline_addr - real_addr);
973 }
974
975 /* handle vga= parameter */

--- 110 unchanged lines hidden (view full) ---

1086
1087 dtb_size = get_image_size(dtb_filename);
1088 if (dtb_size <= 0) {
1089 fprintf(stderr, "qemu: error reading dtb %s: %s\n",
1090 dtb_filename, strerror(errno));
1091 exit(1);
1092 }
1093
969 if (protocol >= 0x202) {
970 stl_p(header + 0x228, cmdline_addr);
971 } else {
972 stw_p(header + 0x20, 0xA33F);
973 stw_p(header + 0x22, cmdline_addr - real_addr);
974 }
975
976 /* handle vga= parameter */

--- 110 unchanged lines hidden (view full) ---

1087
1088 dtb_size = get_image_size(dtb_filename);
1089 if (dtb_size <= 0) {
1090 fprintf(stderr, "qemu: error reading dtb %s: %s\n",
1091 dtb_filename, strerror(errno));
1092 exit(1);
1093 }
1094
1094 setup_data_offset = QEMU_ALIGN_UP(kernel_size, 16);
1095 kernel_size = setup_data_offset + sizeof(SetupData) + dtb_size;
1096 kernel = g_realloc(kernel, kernel_size);
1097
1098
1099 setup_data = (SetupData *)(kernel + setup_data_offset);
1095 setup_data_offset = cmdline_size;
1096 cmdline_size += sizeof(SetupData) + dtb_size;
1097 kernel_cmdline = g_realloc(kernel_cmdline, cmdline_size);
1098 setup_data = (void *)kernel_cmdline + setup_data_offset;
1100 setup_data->next = cpu_to_le64(first_setup_data);
1099 setup_data->next = cpu_to_le64(first_setup_data);
1101 first_setup_data = prot_addr + setup_data_offset;
1100 first_setup_data = cmdline_addr + setup_data_offset;
1102 setup_data->type = cpu_to_le32(SETUP_DTB);
1103 setup_data->len = cpu_to_le32(dtb_size);
1101 setup_data->type = cpu_to_le32(SETUP_DTB);
1102 setup_data->len = cpu_to_le32(dtb_size);
1104
1105 load_image_size(dtb_filename, setup_data->data, dtb_size);
1106 }
1107
1103 load_image_size(dtb_filename, setup_data->data, dtb_size);
1104 }
1105
1108 if (!legacy_no_rng_seed) {
1109 setup_data_offset = QEMU_ALIGN_UP(kernel_size, 16);
1110 kernel_size = setup_data_offset + sizeof(SetupData) + RNG_SEED_LENGTH;
1111 kernel = g_realloc(kernel, kernel_size);
1112 setup_data = (SetupData *)(kernel + setup_data_offset);
1106 if (!legacy_no_rng_seed && protocol >= 0x209) {
1107 setup_data_offset = cmdline_size;
1108 cmdline_size += sizeof(SetupData) + RNG_SEED_LENGTH;
1109 kernel_cmdline = g_realloc(kernel_cmdline, cmdline_size);
1110 setup_data = (void *)kernel_cmdline + setup_data_offset;
1113 setup_data->next = cpu_to_le64(first_setup_data);
1111 setup_data->next = cpu_to_le64(first_setup_data);
1114 first_setup_data = prot_addr + setup_data_offset;
1112 first_setup_data = cmdline_addr + setup_data_offset;
1115 setup_data->type = cpu_to_le32(SETUP_RNG_SEED);
1116 setup_data->len = cpu_to_le32(RNG_SEED_LENGTH);
1117 qemu_guest_getrandom_nofail(setup_data->data, RNG_SEED_LENGTH);
1118 qemu_register_reset_nosnapshotload(reset_rng_seed, setup_data);
1119 fw_cfg_add_bytes_callback(fw_cfg, FW_CFG_KERNEL_DATA, reset_rng_seed, NULL,
1120 setup_data, kernel, kernel_size, true);
1121 } else {
1122 fw_cfg_add_bytes(fw_cfg, FW_CFG_KERNEL_DATA, kernel, kernel_size);
1123 }
1124
1113 setup_data->type = cpu_to_le32(SETUP_RNG_SEED);
1114 setup_data->len = cpu_to_le32(RNG_SEED_LENGTH);
1115 qemu_guest_getrandom_nofail(setup_data->data, RNG_SEED_LENGTH);
1116 qemu_register_reset_nosnapshotload(reset_rng_seed, setup_data);
1117 fw_cfg_add_bytes_callback(fw_cfg, FW_CFG_KERNEL_DATA, reset_rng_seed, NULL,
1118 setup_data, kernel, kernel_size, true);
1119 } else {
1120 fw_cfg_add_bytes(fw_cfg, FW_CFG_KERNEL_DATA, kernel, kernel_size);
1121 }
1122
1123 fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_ADDR, cmdline_addr);
1124 fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_SIZE, cmdline_size);
1125 fw_cfg_add_bytes(fw_cfg, FW_CFG_CMDLINE_DATA, kernel_cmdline, cmdline_size);
1126 sev_load_ctx.cmdline_data = (char *)kernel_cmdline;
1127 sev_load_ctx.cmdline_size = cmdline_size;
1128
1125 fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, prot_addr);
1126 fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_SIZE, kernel_size);
1127 sev_load_ctx.kernel_data = (char *)kernel;
1128 sev_load_ctx.kernel_size = kernel_size;
1129
1130 /*
1131 * If we're starting an encrypted VM, it will be OVMF based, which uses the
1132 * efi stub for booting and doesn't require any values to be placed in the
1133 * kernel header. We therefore don't update the header so the hash of the
1134 * kernel on the other side of the fw_cfg interface matches the hash of the
1135 * file the user passed in.
1136 */
1129 fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, prot_addr);
1130 fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_SIZE, kernel_size);
1131 sev_load_ctx.kernel_data = (char *)kernel;
1132 sev_load_ctx.kernel_size = kernel_size;
1133
1134 /*
1135 * If we're starting an encrypted VM, it will be OVMF based, which uses the
1136 * efi stub for booting and doesn't require any values to be placed in the
1137 * kernel header. We therefore don't update the header so the hash of the
1138 * kernel on the other side of the fw_cfg interface matches the hash of the
1139 * file the user passed in.
1140 */
1137 if (!sev_enabled()) {
1141 if (!sev_enabled() && first_setup_data) {
1138 SetupDataFixup *fixup = g_malloc(sizeof(*fixup));
1139
1140 memcpy(setup, header, MIN(sizeof(header), setup_size));
1141 /* Offset 0x250 is a pointer to the first setup_data link. */
1142 fixup->pos = setup + 0x250;
1143 fixup->orig_val = ldq_p(fixup->pos);
1144 fixup->new_val = first_setup_data;
1145 fixup->addr = cpu_to_le32(real_addr);

--- 380 unchanged lines hidden ---
1142 SetupDataFixup *fixup = g_malloc(sizeof(*fixup));
1143
1144 memcpy(setup, header, MIN(sizeof(header), setup_size));
1145 /* Offset 0x250 is a pointer to the first setup_data link. */
1146 fixup->pos = setup + 0x250;
1147 fixup->orig_val = ldq_p(fixup->pos);
1148 fixup->new_val = first_setup_data;
1149 fixup->addr = cpu_to_le32(real_addr);

--- 380 unchanged lines hidden ---