Introduce the microvm machine type
v10 cover Introduce the microvm machine type
microvm is a machine type inspired by Firecracker and constructed after its machine model.
It's a minimalist machine type without PCI nor ACPI support, designed for short-lived guests. microvm also establishes a baseline for benchmarking and optimizing both QEMU and guest operating systems, since it is optimized for both boot time and footprint.
---
Changelog
v10:
- Fix typo in documentation and cover (Greg Kurz)
- Fix commit message in patch 04/14 (Philippe Mathieu-Daudé)
- Ensure "microvm" appears in lowercase everywhere except in MachineClass and MachineState struct derivatives (Philippe Mathieu-Daudé)
- Add missing components to MICROVM config in Kconfig (Paolo Bonzini, Philippe Mathieu-Daudé)
v9:
- Fix a typo in "[PATCH v9 05/15] hw/i386/pc: avoid an assignment in if condition in x86_load_linux()" (Philippe Mathieu-Daudé)
- Replace qemu_strtol() with qemu_strtoui() to preserve the original type of video_mode (Philippe Mathieu-Daudé)
v8:
- Split "[PATCH v7 03/12] hw/i386/pc: fix code style issues on functions that will be moved out" into four different patches (Philippe Mathieu-Daudé)
v7:
- Fix code style issues on already present code touched by this patch series (Michael S. Tsirkin, Philippe Mathieu-Daudé)
- Add new files to MAINTAINERS (Michael S. Tsirkin, Philippe Mathieu-Daudé)
- Allow starting a microvm machine without a kernel image, fixing "qom-test" (Michael S. Tsirkin)
- Change "bios-microvm.bin" mode to 0644 (Stefano Garzarella)
- Remove unneeded "hw/i386/pc.h" include from x86.c (Stefano Garzarella)
v6:
- Some style fixes (Philippe Mathieu-Daudé)
- Fix a documentation bug stating that LAPIC was in userspace (Paolo Bonzini)
- Update Xen HVM code after X86MachineState introduction (Philippe Mathieu-Daudé)
- Rename header guard from QEMU_VIRTIO_MMIO_H to HW_VIRTIO_MMIO_H (Philippe Mathieu-Daudé)
v5:
- Drop unneeded "[PATCH v4 2/8] hw/i386: Factorize e820 related functions" (Philippe Mathieu-Daudé)
- Drop unneeded "[PATCH v4 1/8] hw/i386: Factorize PVH related functions" (Stefano Garzarella)
- Split X86MachineState introduction into smaller patches (Philippe Mathieu-Daudé)
- Change option-roms to x-option-roms and kernel-cmdline to auto-kernel-cmdline (Paolo Bonzini)
- Make i8259 PIT and i8254 PIC optional (Paolo Bonzini)
- Some fixes to the documentation (Paolo Bonzini)
- Switch documentation format from txt to rst (Peter Maydell)
- Move NMI interface to X86_MACHINE (Philippe Mathieu-Daudé, Paolo Bonzini)
v4:
- This is a complete rewrite of the whole patchset, with a focus on reusing as much existing code as possible to ease the maintenance burden and making the machine type as compatible as possible by default. As a result, the number of lines dedicated specifically to microvm is 383 (code lines measured by "cloc") and, with the default configuration, it's now able to boot both PVH ELF images and bzImages with either SeaBIOS or qboot.
v3:
- Add initrd support (thanks Stefano).
v2:
- Drop "[PATCH 1/4] hw/i386: Factorize CPU routine".
- Simplify machine definition (thanks Eduardo).
- Remove use of unneeded NUMA-related callbacks (thanks Eduardo).
- Add a patch to factorize PVH-related functions.
- Replace use of Linux's Zero Page with PVH (thanks Maran and Paolo).
---
Sergio Lopez (15):
hw/virtio: Factorize virtio-mmio headers
hw/i386/pc: rename functions shared with non-PC machines hw/i386/pc: fix code style issues on functions that will be moved out hw/i386/pc: replace use of strtol with qemu_strtoui in
x86_load_linux()
hw/i386/pc: avoid an assignment in if condition in x86_load_linux() hw/i386/pc: remove commented out code from x86_load_linux() hw/i386/pc: move shared x86 functions to x86.c and export them hw/i386: split PCMachineState deriving X86MachineState from it hw/i386: make x86.c independent from PCMachineState
fw_cfg: add "modify" functions for all types hw/intc/apic: reject pic ints if isa_pic == NULL
roms: add microvm-bios (qboot) as binary and git submodule docs/microvm.rst: document the new microvm machine type hw/i386: Introduce the microvm machine type
MAINTAINERS: add microvm related files
docs/microvm.rst | 98 ++++ default-configs/i386-softmmu.mak | 1 + include/hw/i386/microvm.h | 83 ++++ include/hw/i386/pc.h | 28 +- include/hw/i386/x86.h | 96 ++++ include/hw/nvram/fw_cfg.h | 42 ++ include/hw/virtio/virtio-mmio.h | 73 +++ hw/acpi/cpu_hotplug.c | 10 +- hw/i386/acpi-build.c | 29 +- hw/i386/amd_iommu.c | 3 +- hw/i386/intel_iommu.c | 3 +- hw/i386/microvm.c | 572 ++++++++++++++++++++++ hw/i386/pc.c | 781 +++--------------------------- hw/i386/pc_piix.c | 46 +- hw/i386/pc_q35.c | 38 +- hw/i386/pc_sysfw.c | 60 +-- hw/i386/x86.c | 795 +++++++++++++++++++++++++++++++ hw/i386/xen/xen-hvm.c | 28 +- hw/intc/apic.c | 2 +- hw/intc/ioapic.c | 2 +- hw/nvram/fw_cfg.c | 29 ++ hw/virtio/virtio-mmio.c | 48 +- .gitmodules | 3 + MAINTAINERS | 9 + hw/i386/Kconfig | 10 + hw/i386/Makefile.objs | 2 + pc-bios/bios-microvm.bin | Bin 0 -> 65536 bytes roms/Makefile | 6 + roms/qboot | 1 + 29 files changed, 1987 insertions(+), 911 deletions(-) create mode 100644 docs/microvm.rst create mode 100644 include/hw/i386/microvm.h create mode 100644 include/hw/i386/x86.h create mode 100644 include/hw/virtio/virtio-mmio.h create mode 100644 hw/i386/microvm.c create mode 100644 hw/i386/x86.c create mode 100644 pc-bios/bios-microvm.bin create mode 160000 roms/qboot
Signature · 1 line
2.21.0
PATCH v10 1/15 hw/virtio: Factorize virtio-mmio headers
Put QOM and main struct definition in a separate header file, so it can be accessed from other components.
--- include/hw/virtio/virtio-mmio.h | 73 +++++++++++++++++++++++++++++++++ hw/virtio/virtio-mmio.c | 48 +--------------------- 2 files changed, 74 insertions(+), 47 deletions(-) create mode 100644 include/hw/virtio/virtio-mmio.h
include/hw/virtio/virtio-mmio.h new file +73 -0
@@ -0,0 +1,73 @@ +/* +* Virtio MMIO bindings +* +* Copyright (c) 2011 Linaro Limited +* +* Author: +* Peter Maydell <[email protected]> +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License; either version 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef HW_VIRTIO_MMIO_H +#define HW_VIRTIO_MMIO_H + +#include "hw/virtio/virtio-bus.h" + +/* QOM macros */ +/* virtio-mmio-bus */ +#define TYPE_VIRTIO_MMIO_BUS "virtio-mmio-bus" +#define VIRTIO_MMIO_BUS (obj) \ + OBJECT_CHECK(VirtioBusState, (obj), TYPE_VIRTIO_MMIO_BUS) +#define VIRTIO_MMIO_BUS_GET_CLASS (obj) \ + OBJECT_GET_CLASS(VirtioBusClass, (obj), TYPE_VIRTIO_MMIO_BUS) +#define VIRTIO_MMIO_BUS_CLASS (klass) \ + OBJECT_CLASS_CHECK(VirtioBusClass, (klass), TYPE_VIRTIO_MMIO_BUS) + +/* virtio-mmio */ +#define TYPE_VIRTIO_MMIO "virtio-mmio" +#define VIRTIO_MMIO (obj) \ + OBJECT_CHECK(VirtIOMMIOProxy, (obj), TYPE_VIRTIO_MMIO) + +#define VIRT_MAGIC 0x74726976/* 'virt' */ +#define VIRT_VERSION 2 +#define VIRT_VERSION_LEGACY 1 +#define VIRT_VENDOR 0x554D4551/* 'QEMU' */ + +typedef struct VirtIOMMIOQueue { +uint16_t num; +bool enabled; +uint32_t desc[2 ]; +uint32_t avail[2 ]; +uint32_t used[2 ]; +}VirtIOMMIOQueue ; + +typedef struct { +/* Generic */ +SysBusDevice parent_obj; +MemoryRegion iomem; +qemu_irq irq; +bool legacy; +/* Guest accessible state needing migration and reset */ +uint32_t host_features_sel; +uint32_t guest_features_sel; +uint32_t guest_page_shift; +/* virtio-bus */ +VirtioBusState bus; +bool format_transport_address; +/* Fields only used for non-legacy (v2) devices */ +uint32_t guest_features[2 ]; +VirtIOMMIOQueue vqs[VIRTIO_QUEUE_MAX ]; +}VirtIOMMIOProxy ; + +#endif
hw/virtio/virtio-mmio.c +1 -47
58 lines not on this page · raw message
Signature · 1 line
2.21.0
PATCH v10 2/15 hw/i386/pc: rename functions shared with non-PC machines
In reply to Sergio LopezThe following functions are named *pc* but are not PC-machine specific but generic to the X86 architecture, rename them:
load_linux -> x86_load_linux pc_new_cpu -> x86_new_cpu pc_cpus_init -> x86_cpus_init pc_cpu_index_to_props -> x86_cpu_index_to_props
pc_get_default_cpu_node_id -> x86_get_default_cpu_node_id
pc_possible_cpu_arch_ids -> x86_possible_cpu_arch_ids
old_pc_system_rom_init -> x86_system_rom_init
--- include/hw/i386/pc.h | 2 +- hw/i386/pc.c | 28 ++++++++++++++-------------- hw/i386/pc_piix.c | 2 +- hw/i386/pc_q35.c | 2 +- hw/i386/pc_sysfw.c | 6 +++--- 5 files changed, 20 insertions(+), 20 deletions(-)
include/hw/i386/pc.h +1 -1
@@ -195,7 +195,7 @@ bool pc_machine_is_smm_enabled(PCMachineState *pcms);void pc_register_ferr_irq (qemu_irq irq);void pc_acpi_smi_interrupt (void *opaque,int irq,int level); -void pc_cpus_init (PCMachineState *pcms); +void x86_cpus_init (PCMachineState *pcms);void pc_hot_add_cpu (MachineState *ms,const int64_t id,Error **errp);void pc_smp_parse (MachineState *ms,QemuOpts *opts);
hw/i386/pc.c +14 -14
@@ -1019,8 +1019,8 @@ static bool load_elfboot(const char *kernel_filename,return true; } -static void load_linux (PCMachineState *pcms, -FWCfgState *fw_cfg) +static void x86_load_linux (PCMachineState *pcms, +FWCfgState *fw_cfg) {uint16_t protocol;int setup_size, kernel_size, cmdline_size;
@@ -1374,7 +1374,7 @@ void pc_acpi_smi_interrupt(void *opaque, int irq, int level) } } -static void pc_new_cpu (PCMachineState *pcms,int64_t apic_id,Error **errp) +static void x86_cpu_new (PCMachineState *pcms,int64_t apic_id,Error **errp) {Object *cpu =NULL ;Error *local_err =NULL ;
@@ -1490,14 +1490,14 @@ void pc_hot_add_cpu(MachineState *ms, const int64_t id, Error **errp)return ; } -pc_new_cpu (PC_MACHINE (ms), apic_id, &local_err); +x86_cpu_new (PC_MACHINE (ms), apic_id, &local_err);if (local_err) {error_propagate (errp, local_err);return ; } } -void pc_cpus_init (PCMachineState *pcms) +void x86_cpus_init (PCMachineState *pcms) {int i;const CPUArchIdList *possible_cpus;
@@ -1518,7 +1518,7 @@ void pc_cpus_init(PCMachineState *pcms) ms->smp.max_cpus - 1) + 1; possible_cpus = mc->possible_cpu_arch_ids (ms);for (i =0 ; i < ms->smp.cpus; i++) { -pc_new_cpu (pcms, possible_cpus->cpus[i].arch_id, &error_fatal); +x86_cpu_new (pcms, possible_cpus->cpus[i].arch_id, &error_fatal); } }
@@ -1621,7 +1621,7 @@ void xen_load_linux(PCMachineState *pcms)fw_cfg_add_i16 (fw_cfg,FW_CFG_NB_CPUS , pcms->boot_cpus);rom_set_fw (fw_cfg); -load_linux (pcms, fw_cfg); +x86_load_linux (pcms, fw_cfg);for (i =0 ; i < nb_option_roms; i++) { assert(!strcmp(option_rom[i].name, "linuxboot.bin") || !strcmp(option_rom[i].name, "linuxboot_dma.bin") ||
@@ -1756,7 +1756,7 @@ void pc_memory_init(PCMachineState *pcms, }if (linux_boot) { -load_linux (pcms, fw_cfg); +x86_load_linux (pcms, fw_cfg); }for (i =0 ; i < nb_option_roms; i++) {
@@ -2678,7 +2678,7 @@ static void pc_machine_wakeup(MachineState *machine) }static CpuInstanceProperties -pc_cpu_index_to_props (MachineState *ms,unsigned cpu_index) +x86_cpu_index_to_props (MachineState *ms,unsigned cpu_index) {MachineClass *mc =MACHINE_GET_CLASS (ms);const CPUArchIdList *possible_cpus = mc->possible_cpu_arch_ids (ms);
@@ -2687,7 +2687,7 @@ pc_cpu_index_to_props(MachineState *ms, unsigned cpu_index)return possible_cpus->cpus[cpu_index].props; } -static int64_t pc_get_default_cpu_node_id (const MachineState *ms,int idx) +static int64_t x86_get_default_cpu_node_id (const MachineState *ms,int idx) {X86CPUTopoInfo topo;PCMachineState *pcms =PC_MACHINE (ms);
@@ -2699,7 +2699,7 @@ static int64_t pc_get_default_cpu_node_id(const MachineState *ms, int idx)return topo.pkg_id % ms->numa_state->num_nodes; } -static const CPUArchIdList *pc_possible_cpu_arch_ids (MachineState *ms) +static const CPUArchIdList *x86_possible_cpu_arch_ids (MachineState *ms) {PCMachineState *pcms =PC_MACHINE (ms);int i;
@@ -2801,9 +2801,9 @@ static void pc_machine_class_init(ObjectClass *oc, void *data)assert (!mc->get_hotplug_handler); mc->get_hotplug_handler = pc_get_hotplug_handler; mc->hotplug_allowed = pc_hotplug_allowed; - mc->cpu_index_to_instance_props = pc_cpu_index_to_props; - mc->get_default_cpu_node_id = pc_get_default_cpu_node_id; - mc->possible_cpu_arch_ids = pc_possible_cpu_arch_ids; + mc->cpu_index_to_instance_props = x86_cpu_index_to_props; + mc->get_default_cpu_node_id = x86_get_default_cpu_node_id; + mc->possible_cpu_arch_ids = x86_possible_cpu_arch_ids; mc->auto_enable_numa_with_memhp = true; mc->has_hotpluggable_cpus = true; mc->default_boot_order ="cad" ;
hw/i386/pc_piix.c +1 -1
@@ -152,7 +152,7 @@ static void pc_init1(MachineState *machine, } } -pc_cpus_init (pcms); +x86_cpus_init (pcms);if (kvm_enabled () && pcmc->kvmclock_enabled) {kvmclock_create ();
hw/i386/pc_q35.c +1 -1
@@ -179,7 +179,7 @@ static void pc_q35_init(MachineState *machine)xen_hvm_init (pcms, &ram_memory); } -pc_cpus_init (pcms); +x86_cpus_init (pcms);kvmclock_create ();
hw/i386/pc_sysfw.c +3 -3
@@ -211,7 +211,7 @@ static void pc_system_flash_map(PCMachineState *pcms, } } -static void old_pc_system_rom_init (MemoryRegion *rom_memory,bool isapc_ram_fw) +static void x86_bios_rom_init (MemoryRegion *rom_memory,bool isapc_ram_fw) {char *filename;MemoryRegion *bios, *isa_bios;
@@ -272,7 +272,7 @@ void pc_system_firmware_init(PCMachineState *pcms,BlockBackend *pflash_blk[ARRAY_SIZE (pcms->flash)];if (!pcmc->pci_enabled) { -old_pc_system_rom_init (rom_memory, true); +x86_bios_rom_init (rom_memory, true);return ; }
@@ -293,7 +293,7 @@ void pc_system_firmware_init(PCMachineState *pcms,if (!pflash_blk[0 ]) {/* Machine property pflash0 not set, use ROM mode */ -old_pc_system_rom_init (rom_memory, false); +x86_bios_rom_init (rom_memory, false); }else {if (kvm_enabled () && !kvm_readonly_mem_enabled ()) {/*
Signature · 1 line
2.21.0
PATCH v10 3/15 hw/i386/pc: fix code style issues on functions that will be moved out
In reply to Sergio LopezFix code style issues detected by checkpatch.pl on functions that will be moved out to x86.c.
--- hw/i386/pc.c | 53 ++++++++++++++++++++++++++++------------------------ 1 file changed, 29 insertions(+), 24 deletions(-)
hw/i386/pc.c +29 -24
@@ -866,7 +866,8 @@ static void handle_a20_line_change(void *opaque, int irq, int level)x86_cpu_set_a20 (cpu, level); } -/* Calculates initial APIC ID for a specific CPU index +/* +* Calculates initial APIC ID for a specific CPU index * * Currently we need to be able to calculate the APIC ID from the CPU index * alone (without requiring a CPU object), as the QEMU<->Seabios interfaces have
@@ -1039,7 +1040,7 @@ static void x86_load_linux(PCMachineState *pcms,const char *kernel_cmdline = machine->kernel_cmdline;/* Align to 16 bytes as a paranoia measure */ - cmdline_size = (strlen (kernel_cmdline)+16 ) & ~15 ; + cmdline_size = (strlen (kernel_cmdline) +16 ) & ~15 ;/* load the kernel header */ f =fopen (kernel_filename,"rb" );
@@ -1055,8 +1056,8 @@ static void x86_load_linux(PCMachineState *pcms,#if 0 fprintf (stderr,"header magic: %#x\n" ,ldl_p (header+0x202 ));#endif -if (ldl_p (header+0x202 ) ==0x53726448 ) { - protocol =lduw_p (header+0x206 ); +if (ldl_p (header +0x202 ) ==0x53726448 ) { + protocol =lduw_p (header +0x206 ); }else {/* * This could be a multiboot kernel. If it is, let's stop treating it
@@ -1158,7 +1159,7 @@ static void x86_load_linux(PCMachineState *pcms,/* highest address for loading the initrd */ if (protocol >=0x20c && -lduw_p (header+0x236 ) &XLF_CAN_BE_LOADED_ABOVE_4G ) { +lduw_p (header +0x236 ) &XLF_CAN_BE_LOADED_ABOVE_4G ) {/* * Linux has supported initrd up to 4 GB for a very long time (2007, * long before XLF_CAN_BE_LOADED_ABOVE_4G which was added in 2013),
@@ -1177,7 +1178,7 @@ static void x86_load_linux(PCMachineState *pcms,*/ initrd_max =UINT32_MAX ; }else if (protocol >=0x203 ) { - initrd_max =ldl_p (header+0x22c ); + initrd_max =ldl_p (header +0x22c ); }else { initrd_max =0x37ffffff ; }
@@ -1187,14 +1188,14 @@ static void x86_load_linux(PCMachineState *pcms, }fw_cfg_add_i32 (fw_cfg,FW_CFG_CMDLINE_ADDR , cmdline_addr); -fw_cfg_add_i32 (fw_cfg,FW_CFG_CMDLINE_SIZE ,strlen (kernel_cmdline)+1 ); +fw_cfg_add_i32 (fw_cfg,FW_CFG_CMDLINE_SIZE ,strlen (kernel_cmdline) +1 );fw_cfg_add_string (fw_cfg,FW_CFG_CMDLINE_DATA , kernel_cmdline);if (protocol >=0x202 ) { -stl_p (header+0x228 , cmdline_addr); +stl_p (header +0x228 , cmdline_addr); }else { -stw_p (header+0x20 ,0xA33F ); -stw_p (header+0x22 , cmdline_addr-real_addr); +stw_p (header +0x20 ,0xA33F ); +stw_p (header +0x22 , cmdline_addr - real_addr); }/* handle vga= parameter */
@@ -1212,20 +1213,22 @@ static void x86_load_linux(PCMachineState *pcms, }else { video_mode =strtol (vmode,NULL ,0 ); } -stw_p (header+0x1fa , video_mode); +stw_p (header +0x1fa , video_mode); }/* loader type */ -/* High nybble = B reserved for QEMU; low nybble is revision number. -If this code is substantially changed, you may want to consider -incrementing the revision. */ +/* +* High nybble = B reserved for QEMU; low nybble is revision number. +* If this code is substantially changed, you may want to consider +* incrementing the revision. +*/ if (protocol >=0x200 ) { header[0x210 ] =0xB0 ; }/* heap */ if (protocol >=0x201 ) { - header[0x211 ] |=0x80 ;/* CAN_USE_HEAP */ -stw_p (header+0x224 , cmdline_addr-real_addr-0x200 ); + header[0x211 ] |=0x80 ;/* CAN_USE_HEAP */ +stw_p (header +0x224 , cmdline_addr - real_addr -0x200 ); }/* load initrd */
@@ -1257,14 +1260,14 @@ static void x86_load_linux(PCMachineState *pcms,exit (1 ); } - initrd_addr = (initrd_max-initrd_size) & ~4095 ; + initrd_addr = (initrd_max - initrd_size) & ~4095 ;fw_cfg_add_i32 (fw_cfg,FW_CFG_INITRD_ADDR , initrd_addr);fw_cfg_add_i32 (fw_cfg,FW_CFG_INITRD_SIZE , initrd_size);fw_cfg_add_bytes (fw_cfg,FW_CFG_INITRD_DATA , initrd_data, initrd_size); -stl_p (header+0x218 , initrd_addr); -stl_p (header+0x21c , initrd_size); +stl_p (header +0x218 , initrd_addr); +stl_p (header +0x21c , initrd_size); }/* load kernel and setup */
@@ -1272,7 +1275,7 @@ static void x86_load_linux(PCMachineState *pcms,if (setup_size ==0 ) { setup_size =4 ; } - setup_size = (setup_size+1 )*512 ; + setup_size = (setup_size +1 ) *512 ;if (setup_size > kernel_size) {fprintf (stderr,"qemu: invalid kernel header\n" );exit (1 );
@@ -1310,7 +1313,7 @@ static void x86_load_linux(PCMachineState *pcms, kernel_size = setup_data_offset +sizeof (struct setup_data ) + dtb_size; kernel =g_realloc (kernel, kernel_size); -stq_p (header+0x250 , prot_addr + setup_data_offset); +stq_p (header +0x250 , prot_addr + setup_data_offset); setup_data = (struct setup_data *)(kernel + setup_data_offset); setup_data->next =0 ;
@@ -1507,7 +1510,8 @@ void x86_cpus_init(PCMachineState *pcms)x86_cpu_set_default_version (pcmc->default_cpu_version); -/* Calculates the limit to CPU APIC ID values +/* +* Calculates the limit to CPU APIC ID values * * Limit for the APIC ID value, so that all * CPU APIC IDs are < pcms->apic_id_limit.
@@ -2709,7 +2713,7 @@ static const CPUArchIdList *x86_possible_cpu_arch_ids(MachineState *ms)/* * make sure that max_cpus hasn't changed since the first use, i.e. * -smp hasn't been parsed after it -*/ +*/ assert (ms->possible_cpus->len == max_cpus);return ms->possible_cpus; }
@@ -2722,7 +2726,8 @@ static const CPUArchIdList *x86_possible_cpu_arch_ids(MachineState *ms) ms->possible_cpus->cpus[i].type = ms->cpu_type; ms->possible_cpus->cpus[i].vcpus_count =1 ; - ms->possible_cpus->cpus[i].arch_id =x86_cpu_apic_id_from_index (pcms, i); + ms->possible_cpus->cpus[i].arch_id = +x86_cpu_apic_id_from_index (pcms, i);x86_topo_ids_from_apicid (ms->possible_cpus->cpus[i].arch_id, pcms->smp_dies, ms->smp.cores, ms->smp.threads, &topo);
Signature · 1 line
2.21.0
Re: [PATCH v10 03/15] hw/i386/pc: fix code style issues on functions that will be moved out
Quoted 6 lines · Sergio Lopez
Fix code style issues detected by checkpatch.pl on functions that will be moved out to
x86.c.Signed-off-by Sergio Lopez <[email protected]>Reviewed-by Philippe Mathieu-Daudé <[email protected]>
Quoted 170 lines
--- hw/i386/pc.c | 53 ++++++++++++++++++++++++++++------------------------ 1 file changed, 29 insertions(+), 24 deletions(-)hw/i386/pc.c +29
-25@@ -866,7 +866,8 @@ static void handle_a20_line_change(void *opaque, int irq, int level)x86_cpu_set_a20 (cpu, level); } -/* Calculates initial APIC ID for a specific CPU index +/* +* Calculates initial APIC ID for a specific CPU index * * Currently we need to be able to calculate the APIC ID from the CPU index * alone (without requiring a CPU object), as the QEMU<->Seabios interfaces have @@ -1039,7 +1040,7 @@ static void x86_load_linux(PCMachineState *pcms,const char *kernel_cmdline = machine->kernel_cmdline;/* Align to 16 bytes as a paranoia measure */ - cmdline_size = (strlen (kernel_cmdline)+16 ) & ~15 ; + cmdline_size = (strlen (kernel_cmdline) +16 ) & ~15 ;/* load the kernel header */ f =fopen (kernel_filename,"rb" );@@ -1055,8 +1056,8 @@ static void x86_load_linux(PCMachineState *pcms,#if 0 fprintf (stderr,"header magic: %#x\n" ,ldl_p (header+0x202 ));#endif -if (ldl_p (header+0x202 ) ==0x53726448 ) { - protocol =lduw_p (header+0x206 ); +if (ldl_p (header +0x202 ) ==0x53726448 ) { + protocol =lduw_p (header +0x206 ); }else {/* * This could be a multiboot kernel. If it is, let's stop treating it @@ -1158,7 +1159,7 @@ static void x86_load_linux(PCMachineState *pcms,/* highest address for loading the initrd */ if (protocol >=0x20c && -lduw_p (header+0x236 ) &XLF_CAN_BE_LOADED_ABOVE_4G ) { +lduw_p (header +0x236 ) &XLF_CAN_BE_LOADED_ABOVE_4G ) {/* * Linux has supported initrd up to 4 GB for a very long time (2007, * long before XLF_CAN_BE_LOADED_ABOVE_4G which was added in 2013), @@ -1177,7 +1178,7 @@ static void x86_load_linux(PCMachineState *pcms,*/ initrd_max =UINT32_MAX ; }else if (protocol >=0x203 ) { - initrd_max =ldl_p (header+0x22c ); + initrd_max =ldl_p (header +0x22c ); }else { initrd_max =0x37ffffff ; }@@ -1187,14 +1188,14 @@ static void x86_load_linux(PCMachineState *pcms, }fw_cfg_add_i32 (fw_cfg,FW_CFG_CMDLINE_ADDR , cmdline_addr); -fw_cfg_add_i32 (fw_cfg,FW_CFG_CMDLINE_SIZE ,strlen (kernel_cmdline)+1 ); +fw_cfg_add_i32 (fw_cfg,FW_CFG_CMDLINE_SIZE ,strlen (kernel_cmdline) +1 );fw_cfg_add_string (fw_cfg,FW_CFG_CMDLINE_DATA , kernel_cmdline);if (protocol >=0x202 ) { -stl_p (header+0x228 , cmdline_addr); +stl_p (header +0x228 , cmdline_addr); }else { -stw_p (header+0x20 ,0xA33F ); -stw_p (header+0x22 , cmdline_addr-real_addr); +stw_p (header +0x20 ,0xA33F ); +stw_p (header +0x22 , cmdline_addr - real_addr); }/* handle vga= parameter */ @@ -1212,20 +1213,22 @@ static void x86_load_linux(PCMachineState *pcms, }else { video_mode =strtol (vmode,NULL ,0 ); } -stw_p (header+0x1fa , video_mode); +stw_p (header +0x1fa , video_mode); }/* loader type */ -/* High nybble = B reserved for QEMU; low nybble is revision number. -If this code is substantially changed, you may want to consider -incrementing the revision. */ +/* +* High nybble = B reserved for QEMU; low nybble is revision number. +* If this code is substantially changed, you may want to consider +* incrementing the revision. +*/ if (protocol >=0x200 ) { header[0x210 ] =0xB0 ; }/* heap */ if (protocol >=0x201 ) { - header[0x211 ] |=0x80 ;/* CAN_USE_HEAP */ -stw_p (header+0x224 , cmdline_addr-real_addr-0x200 ); + header[0x211 ] |=0x80 ;/* CAN_USE_HEAP */ +stw_p (header +0x224 , cmdline_addr - real_addr -0x200 ); }/* load initrd */ @@ -1257,14 +1260,14 @@ static void x86_load_linux(PCMachineState *pcms,exit (1 ); } - initrd_addr = (initrd_max-initrd_size) & ~4095 ; + initrd_addr = (initrd_max - initrd_size) & ~4095 ;fw_cfg_add_i32 (fw_cfg,FW_CFG_INITRD_ADDR , initrd_addr);fw_cfg_add_i32 (fw_cfg,FW_CFG_INITRD_SIZE , initrd_size);fw_cfg_add_bytes (fw_cfg,FW_CFG_INITRD_DATA , initrd_data, initrd_size); -stl_p (header+0x218 , initrd_addr); -stl_p (header+0x21c , initrd_size); +stl_p (header +0x218 , initrd_addr); +stl_p (header +0x21c , initrd_size); }/* load kernel and setup */ @@ -1272,7 +1275,7 @@ static void x86_load_linux(PCMachineState *pcms,if (setup_size ==0 ) { setup_size =4 ; } - setup_size = (setup_size+1 )*512 ; + setup_size = (setup_size +1 ) *512 ;if (setup_size > kernel_size) {fprintf (stderr,"qemu: invalid kernel header\n" );exit (1 );@@ -1310,7 +1313,7 @@ static void x86_load_linux(PCMachineState *pcms, kernel_size = setup_data_offset +sizeof (struct setup_data ) + dtb_size; kernel =g_realloc (kernel, kernel_size); -stq_p (header+0x250 , prot_addr + setup_data_offset); +stq_p (header +0x250 , prot_addr + setup_data_offset); setup_data = (struct setup_data *)(kernel + setup_data_offset); setup_data->next =0 ;@@ -1507,7 +1510,8 @@ void x86_cpus_init(PCMachineState *pcms)x86_cpu_set_default_version (pcmc->default_cpu_version); -/* Calculates the limit to CPU APIC ID values +/* +* Calculates the limit to CPU APIC ID values * * Limit for the APIC ID value, so that all * CPU APIC IDs are < pcms->apic_id_limit. @@ -2709,7 +2713,7 @@ static const CPUArchIdList *x86_possible_cpu_arch_ids(MachineState *ms)/* * make sure that max_cpus hasn't changed since the first use, i.e. * -smp hasn't been parsed after it -*/ +*/ assert (ms->possible_cpus->len == max_cpus);return ms->possible_cpus; }@@ -2722,7 +2726,8 @@ static const CPUArchIdList *x86_possible_cpu_arch_ids(MachineState *ms) ms->possible_cpus->cpus[i].type = ms->cpu_type; ms->possible_cpus->cpus[i].vcpus_count =1 ; - ms->possible_cpus->cpus[i].arch_id =x86_cpu_apic_id_from_index (pcms, i); + ms->possible_cpus->cpus[i].arch_id = +x86_cpu_apic_id_from_index (pcms, i);x86_topo_ids_from_apicid (ms->possible_cpus->cpus[i].arch_id, pcms->smp_dies, ms->smp.cores, ms->smp.threads, &topo); --
Quoted 3 lines
2.21.0
--
Marc-André Lureau
PATCH v10 4/15 hw/i386/pc: replace use of strtol with qemu_strtoui in x86_load_linux()
In reply to Sergio LopezFollow checkpatch.pl recommendation and replace the use of strtol with qemu_strtoui in x86_load_linux().
--- hw/i386/pc.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)
hw/i386/pc.c +8 -1
@@ -68,6 +68,7 @@#include "qemu/config-file.h" #include "qemu/error-report.h" #include "qemu/option.h" +#include "qemu/cutils.h" #include "hw/acpi/acpi.h" #include "hw/acpi/cpu_hotplug.h" #include "hw/boards.h"
@@ -1202,6 +1203,7 @@ static void x86_load_linux(PCMachineState *pcms, vmode =strstr (kernel_cmdline,"vga=" );if (vmode) {unsigned int video_mode; +int ret;/* skip "vga=" */ vmode +=4 ;if (!strncmp (vmode,"normal" ,6 )) {
@@ -1211,7 +1213,12 @@ static void x86_load_linux(PCMachineState *pcms, }else if (!strncmp (vmode,"ask" ,3 )) { video_mode =0xfffd ; }else { - video_mode =strtol (vmode,NULL ,0 ); + ret =qemu_strtoui (vmode,NULL ,0 , &video_mode); +if (ret !=0 ) { +fprintf (stderr,"qemu: can't parse 'vga' parameter: %s\n" , +strerror (-ret)); +exit (1 ); + } }stw_p (header +0x1fa , video_mode); }
Signature · 1 line
2.21.0
Re: [PATCH v10 04/15] hw/i386/pc: replace use of strtol with qemu_strtoui in x86_load_linux()
Quoted 6 lines · Sergio Lopez
Follow checkpatch.pl recommendation and replace the use of strtol with
qemu_strtouiinx86_load_linux().Signed-off-by Sergio Lopez <[email protected]>Reviewed-by Philippe Mathieu-Daudé <[email protected]>
Quoted 39 lines
--- hw/i386/pc.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)hw/i386/pc.c +8
-2@@ -68,6 +68,7 @@#include "qemu/config-file.h" #include "qemu/error-report.h" #include "qemu/option.h" +#include "qemu/cutils.h" #include "hw/acpi/acpi.h" #include "hw/acpi/cpu_hotplug.h" #include "hw/boards.h" @@ -1202,6 +1203,7 @@ static void x86_load_linux(PCMachineState *pcms, vmode =strstr (kernel_cmdline,"vga=" );if (vmode) {unsigned int video_mode; +int ret;/* skip "vga=" */ vmode +=4 ;if (!strncmp (vmode,"normal" ,6 )) {@@ -1211,7 +1213,12 @@ static void x86_load_linux(PCMachineState *pcms, }else if (!strncmp (vmode,"ask" ,3 )) { video_mode =0xfffd ; }else { - video_mode =strtol (vmode,NULL ,0 ); + ret =qemu_strtoui (vmode,NULL ,0 , &video_mode); +if (ret !=0 ) { +fprintf (stderr,"qemu: can't parse 'vga' parameter: %s\n" , +strerror (-ret)); +exit (1 ); + } }stw_p (header +0x1fa , video_mode); } --
Quoted 3 lines
2.21.0
--
Marc-André Lureau
PATCH v10 5/15 hw/i386/pc: avoid an assignment in if condition in x86_load_linux()
In reply to Sergio LopezFollow checkpatch.pl recommendation and avoid an assignment in if condition in x86_load_linux().
--- hw/i386/pc.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)
hw/i386/pc.c +8 -1
@@ -1045,7 +1045,14 @@ static void x86_load_linux(PCMachineState *pcms,/* load the kernel header */ f =fopen (kernel_filename,"rb" ); -if (!f || !(kernel_size =get_file_size (f)) || +if (!f) { +fprintf (stderr,"qemu: could not open kernel file '%s': %s\n" , + kernel_filename,strerror (errno)); +exit (1 ); + } + + kernel_size =get_file_size (f); +if (!kernel_size ||fread (header,1 ,MIN (ARRAY_SIZE (header), kernel_size), f) !=MIN (ARRAY_SIZE (header), kernel_size)) { fprintf(stderr, "qemu: could not load kernel '%s': %s\n",
Signature · 1 line
2.21.0
PATCH v10 6/15 hw/i386/pc: remove commented out code from x86_load_linux()
In reply to Sergio LopezFollow checkpatch.pl recommendation and remove commented out code from x86_load_linux().
--- hw/i386/pc.c | 13 ------------- 1 file changed, 13 deletions(-)
hw/i386/pc.c +0 -13
@@ -1061,9 +1061,6 @@ static void x86_load_linux(PCMachineState *pcms, }/* kernel protocol version */ -#if 0 -fprintf (stderr,"header magic: %#x\n" ,ldl_p (header+0x202 )); -#endif if (ldl_p (header +0x202 ) ==0x53726448 ) { protocol =lduw_p (header +0x206 ); }else {
@@ -1155,16 +1152,6 @@ static void x86_load_linux(PCMachineState *pcms, prot_addr =0x100000 ; } -#if 0 -fprintf (stderr, -"qemu: real_addr = 0x" TARGET_FMT_plx"\n" -"qemu: cmdline_addr = 0x" TARGET_FMT_plx"\n" -"qemu: prot_addr = 0x" TARGET_FMT_plx"\n" , - real_addr, - cmdline_addr, - prot_addr); -#endif -/* highest address for loading the initrd */ if (protocol >=0x20c &&lduw_p (header +0x236 ) &XLF_CAN_BE_LOADED_ABOVE_4G ) {
Signature · 1 line
2.21.0
PATCH v10 7/15 hw/i386/pc: move shared x86 functions to x86.c and export them
In reply to Sergio LopezMove x86 functions that will be shared between PC and non-PC machine types to x86.c, along with their helpers.
--- include/hw/i386/pc.h | 1 - include/hw/i386/x86.h | 35 +++ hw/i386/pc.c | 587 +---------------------------------- hw/i386/pc_piix.c | 1 + hw/i386/pc_q35.c | 1 + hw/i386/pc_sysfw.c | 56 +--- hw/i386/x86.c | 690 ++++++++++++++++++++++++++++++++++++++++++ hw/i386/Makefile.objs | 1 + 8 files changed, 730 insertions(+), 642 deletions(-) create mode 100644 include/hw/i386/x86.h create mode 100644 hw/i386/x86.c
include/hw/i386/pc.h +0 -1
@@ -195,7 +195,6 @@ bool pc_machine_is_smm_enabled(PCMachineState *pcms);void pc_register_ferr_irq (qemu_irq irq);void pc_acpi_smi_interrupt (void *opaque,int irq,int level); -void x86_cpus_init (PCMachineState *pcms);void pc_hot_add_cpu (MachineState *ms,const int64_t id,Error **errp);void pc_smp_parse (MachineState *ms,QemuOpts *opts);
include/hw/i386/x86.h new file +35 -0
@@ -0,0 +1,35 @@ +/* +* Copyright (c) 2019 Red Hat, Inc. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2 or later, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef HW_I386_X86_H +#define HW_I386_X86_H + +#include "hw/boards.h" + +uint32_t x86_cpu_apic_id_from_index (PCMachineState *pcms, +unsigned int cpu_index); +void x86_cpu_new (PCMachineState *pcms,int64_t apic_id,Error **errp); +void x86_cpus_init (PCMachineState *pcms); +CpuInstanceProperties x86_cpu_index_to_props (MachineState *ms, +unsigned cpu_index); +int64_t x86_get_default_cpu_node_id (const MachineState *ms,int idx); +const CPUArchIdList *x86_possible_cpu_arch_ids (MachineState *ms); + +void x86_bios_rom_init (MemoryRegion *rom_memory,bool isapc_ram_fw); + +void x86_load_linux (PCMachineState *x86ms,FWCfgState *fw_cfg); + +#endif
hw/i386/pc.c +1 -586
623 lines not on this page · raw message
hw/i386/pc_piix.c +1 -0
@@ -27,6 +27,7 @@#include "qemu/units.h" #include "hw/loader.h" +#include "hw/i386/x86.h" #include "hw/i386/pc.h" #include "hw/i386/apic.h" #include "hw/display/ramfb.h"
hw/i386/pc_q35.c +1 -0
@@ -41,6 +41,7 @@#include "hw/pci-host/q35.h" #include "hw/qdev-properties.h" #include "exec/address-spaces.h" +#include "hw/i386/x86.h" #include "hw/i386/pc.h" #include "hw/i386/ich9.h" #include "hw/i386/amd_iommu.h"
hw/i386/pc_sysfw.c +1 -55
74 lines not on this page · raw message
hw/i386/x86.c new file +690 -0
690 lines not on this page · raw message
hw/i386/Makefile.objs +1 -0
@@ -1,5 +1,6 @@ obj-$(CONFIG_KVM) += kvm/ obj-y += e820_memory_layout.o multiboot.o +obj-y += x86.o obj-y += pc.o obj-$(CONFIG_I440FX) += pc_piix.o obj-$(CONFIG_Q35) += pc_q35.o
Signature · 1 line
2.21.0
PATCH v10 8/15 hw/i386: split PCMachineState deriving X86MachineState from it
In reply to Sergio LopezSplit up PCMachineState and PCMachineClass and derive X86MachineState and X86MachineClass from them. This allows sharing code with non-PC x86 machine types.
--- include/hw/i386/pc.h | 27 +------ include/hw/i386/x86.h | 58 +++++++++++++- hw/acpi/cpu_hotplug.c | 10 +-- hw/i386/acpi-build.c | 29 ++++--- hw/i386/amd_iommu.c | 3 +- hw/i386/intel_iommu.c | 3 +- hw/i386/pc.c | 178 ++++++++++++++---------------------------- hw/i386/pc_piix.c | 43 +++++----- hw/i386/pc_q35.c | 35 +++++---- hw/i386/x86.c | 140 +++++++++++++++++++++++++++++---- hw/i386/xen/xen-hvm.c | 28 ++++--- hw/intc/ioapic.c | 2 +- 12 files changed, 326 insertions(+), 230 deletions(-)
include/hw/i386/pc.h +3 -24
@@ -8,6 +8,7 @@#include "hw/block/flash.h" #include "net/net.h" #include "hw/i386/ioapic.h" +#include "hw/i386/x86.h" #include "qemu/range.h" #include "qemu/bitmap.h"
@@ -27,7 +28,7 @@*/ struct PCMachineState {/*< private >*/ -MachineState parent_obj; +X86MachineState parent_obj;/* <public> */
@@ -36,16 +37,11 @@ struct PCMachineState {/* Pointers to devices and objects: */ HotplugHandler *acpi_dev; -ISADevice *rtc;PCIBus *bus;I2CBus *smbus; -FWCfgState *fw_cfg; -qemu_irq *gsi;PFlashCFI01 *flash[2 ]; -GMappedFile *initrd_mapped_file;/* Configuration options: */ -uint64_t max_ram_below_4g;OnOffAuto vmport;OnOffAuto smm;
@@ -54,27 +50,13 @@ struct PCMachineState {bool sata_enabled;bool pit_enabled; -/* RAM information (sizes, addresses, configuration): */ -ram_addr_t below_4g_mem_size, above_4g_mem_size; - -/* CPU and apic information: */ -bool apic_xrupt_override; -unsigned apic_id_limit; -uint16_t boot_cpus; -unsigned smp_dies; -/* NUMA information: */ uint64_t numa_nodes;uint64_t *node_mem; - -/* Address space used by IOAPIC device. All IOAPIC interrupts -* will be translated to MSI messages in the address space. */ -AddressSpace *ioapic_as; };#define PC_MACHINE_ACPI_DEVICE_PROP "acpi-device"#define PC_MACHINE_DEVMEM_REGION_SIZE "device-memory-region-size" -#define PC_MACHINE_MAX_RAM_BELOW_4G "max-ram-below-4g"#define PC_MACHINE_VMPORT "vmport"#define PC_MACHINE_SMM "smm"#define PC_MACHINE_SMBUS "smbus"
@@ -99,7 +81,7 @@ struct PCMachineState {*/ typedef struct PCMachineClass { /*< private >*/ - MachineClass parent_class; + X86MachineClass parent_class; /*< public >*/
@@ -141,9 +123,6 @@ typedef struct PCMachineClass {/* use PVH to load kernels that support this feature */ bool pvh_enabled; - -/* Enables contiguous-apic-ID mode */ -bool compat_apic_id_mode; } PCMachineClass;#define TYPE_PC_MACHINE "generic-pc-machine"
include/hw/i386/x86.h +57 -1
70 lines not on this page · raw message
hw/acpi/cpu_hotplug.c +5 -5
@@ -128,7 +128,7 @@ void build_legacy_cpu_hotplug_aml(Aml *ctx, MachineState *machine,Aml *one =aml_int (1 );MachineClass *mc =MACHINE_GET_CLASS (machine);const CPUArchIdList *apic_ids = mc->possible_cpu_arch_ids (machine); -PCMachineState *pcms =PC_MACHINE (machine); +X86MachineState *x86ms =X86_MACHINE (machine);/* * _MAT method - creates an madt apic buffer
@@ -236,9 +236,9 @@ void build_legacy_cpu_hotplug_aml(Aml *ctx, MachineState *machine,/* The current AML generator can cover the APIC ID range [0..255], * inclusive, for VCPU hotplug. */ QEMU_BUILD_BUG_ON (ACPI_CPU_HOTPLUG_ID_LIMIT >256 ); -if (pcms->apic_id_limit >ACPI_CPU_HOTPLUG_ID_LIMIT ) { +if (x86ms->apic_id_limit >ACPI_CPU_HOTPLUG_ID_LIMIT ) {error_report ("max_cpus is too large. APIC ID of last CPU is %u" , - pcms->apic_id_limit -1 ); + x86ms->apic_id_limit -1 );exit (1 ); }
@@ -315,8 +315,8 @@ void build_legacy_cpu_hotplug_aml(Aml *ctx, MachineState *machine,* ith up to 255 elements. Windows guests up to win2k8 fail when * VarPackageOp is used. */ - pkg = pcms->apic_id_limit <=255 ?aml_package (pcms->apic_id_limit) : -aml_varpackage (pcms->apic_id_limit); + pkg = x86ms->apic_id_limit <=255 ?aml_package (x86ms->apic_id_limit) : +aml_varpackage (x86ms->apic_id_limit);for (i =0 , apic_idx =0 ; i < apic_ids->len; i++) {int apic_id = apic_ids->cpus[i].arch_id;
hw/i386/acpi-build.c +17 -12
@@ -361,6 +361,7 @@ static void build_madt(GArray *table_data, BIOSLinker *linker, PCMachineState *pcms) {MachineClass *mc =MACHINE_GET_CLASS (pcms); +X86MachineState *x86ms =X86_MACHINE (pcms);const CPUArchIdList *apic_ids = mc->possible_cpu_arch_ids (MACHINE (pcms));int madt_start = table_data->len;AcpiDeviceIfClass *adevc =ACPI_DEVICE_IF_GET_CLASS (pcms->acpi_dev);
@@ -390,7 +391,7 @@ build_madt(GArray *table_data, BIOSLinker *linker, PCMachineState *pcms) io_apic->address =cpu_to_le32 (IO_APIC_DEFAULT_ADDRESS ); io_apic->interrupt =cpu_to_le32 (0 ); -if (pcms->apic_xrupt_override) { +if (x86ms->apic_xrupt_override) { intsrcovr =acpi_data_push (table_data,sizeof *intsrcovr); intsrcovr->type =ACPI_APIC_XRUPT_OVERRIDE ; intsrcovr->length =sizeof (*intsrcovr);
@@ -1831,6 +1832,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,CrsRangeSet crs_range_set;PCMachineState *pcms =PC_MACHINE (machine);PCMachineClass *pcmc =PC_MACHINE_GET_CLASS (machine); +X86MachineState *x86ms =X86_MACHINE (machine);AcpiMcfgInfo mcfg;uint32_t nr_mem = machine->ram_slots;int root_bus_limit =0xFF ;
@@ -2098,7 +2100,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,* with half of the 16-bit control register. Hence, the total size * of the i/o region used is FW_CFG_CTL_SIZE; when using DMA, the * DMA control register is located at FW_CFG_DMA_IO_BASE + 4 */ -uint8_t io_size =object_property_get_bool (OBJECT (pcms->fw_cfg), +uint8_t io_size =object_property_get_bool (OBJECT (x86ms->fw_cfg),"dma_enabled" ,NULL ) ?ROUND_UP (FW_CFG_CTL_SIZE ,4 ) +sizeof (dma_addr_t) :FW_CFG_CTL_SIZE ;
@@ -2331,6 +2333,7 @@ build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine)int srat_start, numa_start, slots;uint64_t mem_len, mem_base, next_base;MachineClass *mc =MACHINE_GET_CLASS (machine); +X86MachineState *x86ms =X86_MACHINE (machine);const CPUArchIdList *apic_ids = mc->possible_cpu_arch_ids (machine);PCMachineState *pcms =PC_MACHINE (machine); ram_addr_t hotplugabble_address_space_size =
@@ -2401,16 +2404,16 @@ build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine) }/* Cut out the ACPI_PCI hole */ -if (mem_base <= pcms->below_4g_mem_size && - next_base > pcms->below_4g_mem_size) { - mem_len -= next_base - pcms->below_4g_mem_size; +if (mem_base <= x86ms->below_4g_mem_size && + next_base > x86ms->below_4g_mem_size) { + mem_len -= next_base - x86ms->below_4g_mem_size;if (mem_len >0 ) { numamem =acpi_data_push (table_data,sizeof *numamem);build_srat_memory (numamem, mem_base, mem_len, i -1 ,MEM_AFFINITY_ENABLED ); } mem_base =1ULL <<32 ; - mem_len = next_base - pcms->below_4g_mem_size; + mem_len = next_base - x86ms->below_4g_mem_size; next_base = mem_base + mem_len; }
@@ -2629,6 +2632,7 @@ void acpi_build(AcpiBuildTables *tables, MachineState *machine) {PCMachineState *pcms =PC_MACHINE (machine);PCMachineClass *pcmc =PC_MACHINE_GET_CLASS (pcms); +X86MachineState *x86ms =X86_MACHINE (machine);GArray *table_offsets;unsigned facs, dsdt, rsdt, fadt;AcpiPmInfo pm;
@@ -2790,7 +2794,7 @@ void acpi_build(AcpiBuildTables *tables, MachineState *machine)*/ int legacy_aml_len = pcmc->legacy_acpi_table_size + -ACPI_BUILD_LEGACY_CPU_AML_SIZE * pcms->apic_id_limit; +ACPI_BUILD_LEGACY_CPU_AML_SIZE * x86ms->apic_id_limit;int legacy_table_size =ROUND_UP (tables_blob->len - aml_len + legacy_aml_len,ACPI_BUILD_ALIGN_SIZE );
@@ -2880,13 +2884,14 @@ void acpi_setup(void) {PCMachineState *pcms =PC_MACHINE (qdev_get_machine ());PCMachineClass *pcmc =PC_MACHINE_GET_CLASS (pcms); +X86MachineState *x86ms =X86_MACHINE (pcms);AcpiBuildTables tables;AcpiBuildState *build_state;Object *vmgenid_dev;TPMIf *tpm;static FwCfgTPMConfig tpm_config; -if (!pcms->fw_cfg) { +if (!x86ms->fw_cfg) {ACPI_BUILD_DPRINTF ("No fw cfg. Bailing out.\n" );return ; }
@@ -2917,7 +2922,7 @@ void acpi_setup(void)acpi_add_rom_blob (acpi_build_update, build_state, tables.linker->cmd_blob,"etc/table-loader" ,0 ); -fw_cfg_add_file (pcms->fw_cfg,ACPI_BUILD_TPMLOG_FILE , +fw_cfg_add_file (x86ms->fw_cfg,ACPI_BUILD_TPMLOG_FILE , tables.tcpalog->data,acpi_data_len (tables.tcpalog)); tpm =tpm_find ();
@@ -2927,13 +2932,13 @@ void acpi_setup(void) .tpm_version = tpm_get_version(tpm), .tpmppi_version = TPM_PPI_VERSION_1_30 }; -fw_cfg_add_file (pcms->fw_cfg,"etc/tpm/config" , +fw_cfg_add_file (x86ms->fw_cfg,"etc/tpm/config" , &tpm_config,sizeof tpm_config); } vmgenid_dev =find_vmgenid_dev ();if (vmgenid_dev) { -vmgenid_add_fw_cfg (VMGENID (vmgenid_dev), pcms->fw_cfg, +vmgenid_add_fw_cfg (VMGENID (vmgenid_dev), x86ms->fw_cfg, tables.vmgenid); }
@@ -2946,7 +2951,7 @@ void acpi_setup(void)uint32_t rsdp_size =acpi_data_len (tables.rsdp); build_state->rsdp =g_memdup (tables.rsdp->data, rsdp_size); -fw_cfg_add_file_callback (pcms->fw_cfg,ACPI_BUILD_RSDP_FILE , +fw_cfg_add_file_callback (x86ms->fw_cfg,ACPI_BUILD_RSDP_FILE , acpi_build_update,NULL , build_state, build_state->rsdp, rsdp_size, true); build_state->rsdp_mr =NULL ;
hw/i386/amd_iommu.c +2 -1
@@ -1540,6 +1540,7 @@ static void amdvi_realize(DeviceState *dev, Error **err)X86IOMMUState *x86_iommu =X86_IOMMU_DEVICE (dev);MachineState *ms =MACHINE (qdev_get_machine ());PCMachineState *pcms =PC_MACHINE (ms); +X86MachineState *x86ms =X86_MACHINE (ms);PCIBus *bus = pcms->bus; s->iotlb = g_hash_table_new_full(amdvi_uint64_hash,
@@ -1568,7 +1569,7 @@ static void amdvi_realize(DeviceState *dev, Error **err) }/* Pseudo address space under root PCI bus. */ - pcms->ioapic_as =amdvi_host_dma_iommu (bus, s,AMDVI_IOAPIC_SB_DEVID ); + x86ms->ioapic_as =amdvi_host_dma_iommu (bus, s,AMDVI_IOAPIC_SB_DEVID );/* set up MMIO */ memory_region_init_io(&s->mmio, OBJECT(s), &mmio_mem_ops, s, "amdvi-mmio",
hw/i386/intel_iommu.c +2 -1
@@ -3733,6 +3733,7 @@ static void vtd_realize(DeviceState *dev, Error **errp) {MachineState *ms =MACHINE (qdev_get_machine ());PCMachineState *pcms =PC_MACHINE (ms); +X86MachineState *x86ms =X86_MACHINE (ms);PCIBus *bus = pcms->bus;IntelIOMMUState *s =INTEL_IOMMU_DEVICE (dev);X86IOMMUState *x86_iommu =X86_IOMMU_DEVICE (dev);
@@ -3773,7 +3774,7 @@ static void vtd_realize(DeviceState *dev, Error **errp)sysbus_mmio_map (SYS_BUS_DEVICE (s),0 ,Q35_HOST_BRIDGE_IOMMU_ADDR );pci_setup_iommu (bus, vtd_host_dma_iommu, dev);/* Pseudo address space under root PCI bus. */ - pcms->ioapic_as =vtd_host_dma_iommu (bus, s,Q35_PSEUDO_DEVFN_IOAPIC ); + x86ms->ioapic_as =vtd_host_dma_iommu (bus, s,Q35_PSEUDO_DEVFN_IOAPIC );qemu_add_machine_init_done_notifier (&vtd_machine_done_notify); }
hw/i386/pc.c +59 -119
454 lines not on this page · raw message
hw/i386/pc_piix.c +22 -21
124 lines not on this page · raw message
hw/i386/pc_q35.c +18 -17
@@ -116,6 +116,7 @@ static void pc_q35_init(MachineState *machine) {PCMachineState *pcms =PC_MACHINE (machine);PCMachineClass *pcmc =PC_MACHINE_GET_CLASS (pcms); +X86MachineState *x86ms =X86_MACHINE (machine);Q35PCIHost *q35_host;PCIHostState *phb;PCIBus *host_bus;
@@ -153,27 +154,27 @@ static void pc_q35_init(MachineState *machine)/* Handle the machine opt max-ram-below-4g. It is basically doing * min(qemu limit, user limit). */ -if (!pcms->max_ram_below_4g) { - pcms->max_ram_below_4g =1ULL <<32 ;/* default: 4G */ ; +if (!x86ms->max_ram_below_4g) { + x86ms->max_ram_below_4g =4 * GiB; } -if (lowmem > pcms->max_ram_below_4g) { - lowmem = pcms->max_ram_below_4g; +if (lowmem > x86ms->max_ram_below_4g) { + lowmem = x86ms->max_ram_below_4g;if (machine->ram_size - lowmem > lowmem && lowmem & (1 * GiB -1 )) {warn_report ("There is possibly poor performance as the ram size " " (0x%" PRIx64") is more then twice the size of" " max-ram-below-4g (%" PRIu64") and" " max-ram-below-4g is not a multiple of 1G." , - (uint64_t )machine->ram_size, pcms->max_ram_below_4g); + (uint64_t )machine->ram_size, x86ms->max_ram_below_4g); } }if (machine->ram_size >= lowmem) { - pcms->above_4g_mem_size = machine->ram_size - lowmem; - pcms->below_4g_mem_size = lowmem; + x86ms->above_4g_mem_size = machine->ram_size - lowmem; + x86ms->below_4g_mem_size = lowmem; }else { - pcms->above_4g_mem_size =0 ; - pcms->below_4g_mem_size = machine->ram_size; + x86ms->above_4g_mem_size =0 ; + x86ms->below_4g_mem_size = machine->ram_size; }if (xen_enabled ()) {
@@ -214,10 +215,10 @@ static void pc_q35_init(MachineState *machine) gsi_state =g_malloc0 (sizeof (*gsi_state));if (kvm_ioapic_in_kernel ()) {kvm_pc_setup_irq_routing (pcmc->pci_enabled); - pcms->gsi =qemu_allocate_irqs (kvm_pc_gsi_handler, gsi_state, + x86ms->gsi =qemu_allocate_irqs (kvm_pc_gsi_handler, gsi_state,GSI_NUM_PINS ); }else { - pcms->gsi =qemu_allocate_irqs (gsi_handler, gsi_state,GSI_NUM_PINS ); + x86ms->gsi =qemu_allocate_irqs (gsi_handler, gsi_state,GSI_NUM_PINS ); }/* create pci host bus */
@@ -232,9 +233,9 @@ static void pc_q35_init(MachineState *machine) MCH_HOST_PROP_SYSTEM_MEM, NULL);object_property_set_link (OBJECT (q35_host),OBJECT (system_io),MCH_HOST_PROP_IO_MEM ,NULL ); -object_property_set_int (OBJECT (q35_host), pcms->below_4g_mem_size, +object_property_set_int (OBJECT (q35_host), x86ms->below_4g_mem_size,PCI_HOST_BELOW_4G_MEM_SIZE ,NULL ); -object_property_set_int (OBJECT (q35_host), pcms->above_4g_mem_size, +object_property_set_int (OBJECT (q35_host), x86ms->above_4g_mem_size,PCI_HOST_ABOVE_4G_MEM_SIZE ,NULL );/* pci */ qdev_init_nofail (DEVICE (q35_host));
@@ -256,7 +257,7 @@ static void pc_q35_init(MachineState *machine) ich9_lpc =ICH9_LPC_DEVICE (lpc); lpc_dev =DEVICE (lpc);for (i =0 ; i <GSI_NUM_PINS ; i++) { -qdev_connect_gpio_out_named (lpc_dev,ICH9_GPIO_GSI , i, pcms->gsi[i]); +qdev_connect_gpio_out_named (lpc_dev,ICH9_GPIO_GSI , i, x86ms->gsi[i]); }pci_bus_irqs (host_bus, ich9_lpc_set_irq, ich9_lpc_map_irq, ich9_lpc,ICH9_LPC_NB_PIRQS );
@@ -280,7 +281,7 @@ static void pc_q35_init(MachineState *machine)ioapic_init_gsi (gsi_state,"q35" ); } -pc_register_ferr_irq (pcms->gsi[13 ]); +pc_register_ferr_irq (x86ms->gsi[13 ]);assert (pcms->vmport !=ON_OFF_AUTO__MAX );if (pcms->vmport ==ON_OFF_AUTO_AUTO ) {
@@ -288,7 +289,7 @@ static void pc_q35_init(MachineState *machine) }/* init basic PC hardware */ -pc_basic_device_init (isa_bus, pcms->gsi, &rtc_state, !mc->no_floppy, +pc_basic_device_init (isa_bus, x86ms->gsi, &rtc_state, !mc->no_floppy, (pcms->vmport !=ON_OFF_AUTO_ON ), pcms->pit_enabled,0xff0104 );
@@ -331,7 +332,7 @@ static void pc_q35_init(MachineState *machine)if (machine->nvdimms_state->is_enabled) {nvdimm_init_acpi_state (machine->nvdimms_state, system_io, - pcms->fw_cfg,OBJECT (pcms)); + x86ms->fw_cfg,OBJECT (pcms)); } }
hw/i386/x86.c +125 -15
232 lines not on this page · raw message
hw/i386/xen/xen-hvm.c +15 -13
@@ -197,11 +197,13 @@ qemu_irq *xen_interrupt_controller_init(void)static void xen_ram_init (PCMachineState *pcms,ram_addr_t ram_size,MemoryRegion **ram_memory_p) { +X86MachineState *x86ms =X86_MACHINE (pcms);MemoryRegion *sysmem =get_system_memory ();ram_addr_t block_len; -uint64_t user_lowmem =object_property_get_uint (qdev_get_machine (), -PC_MACHINE_MAX_RAM_BELOW_4G , - &error_abort); +uint64_t user_lowmem = +object_property_get_uint (qdev_get_machine (), +X86_MACHINE_MAX_RAM_BELOW_4G , + &error_abort);/* Handle the machine opt max-ram-below-4g. It is basically doing * min(xen limit, user limit).
@@ -214,20 +216,20 @@ static void xen_ram_init(PCMachineState *pcms, }if (ram_size >= user_lowmem) { - pcms->above_4g_mem_size = ram_size - user_lowmem; - pcms->below_4g_mem_size = user_lowmem; + x86ms->above_4g_mem_size = ram_size - user_lowmem; + x86ms->below_4g_mem_size = user_lowmem; }else { - pcms->above_4g_mem_size =0 ; - pcms->below_4g_mem_size = ram_size; + x86ms->above_4g_mem_size =0 ; + x86ms->below_4g_mem_size = ram_size; } -if (!pcms->above_4g_mem_size) { +if (!x86ms->above_4g_mem_size) { block_len = ram_size; }else {/* * Xen does not allocate the memory continuously, it keeps a * hole of the size computed above or passed in. */ - block_len = (1ULL <<32 ) + pcms->above_4g_mem_size; + block_len = (1ULL <<32 ) + x86ms->above_4g_mem_size; }memory_region_init_ram (&ram_memory,NULL ,"xen.ram" , block_len, &error_fatal);
@@ -244,12 +246,12 @@ static void xen_ram_init(PCMachineState *pcms,*/ memory_region_init_alias (&ram_lo,NULL ,"xen.ram.lo" , &ram_memory,0xc0000 , - pcms->below_4g_mem_size -0xc0000 ); + x86ms->below_4g_mem_size -0xc0000 );memory_region_add_subregion (sysmem,0xc0000 , &ram_lo); -if (pcms->above_4g_mem_size >0 ) { +if (x86ms->above_4g_mem_size >0 ) {memory_region_init_alias (&ram_hi,NULL ,"xen.ram.hi" , &ram_memory,0x100000000ULL , - pcms->above_4g_mem_size); + x86ms->above_4g_mem_size);memory_region_add_subregion (sysmem,0x100000000ULL , &ram_hi); } }
@@ -265,7 +267,7 @@ void xen_ram_alloc(ram_addr_t ram_addr, ram_addr_t size, MemoryRegion *mr,/* RAM already populated in Xen */ fprintf (stderr,"%s: do not alloc " RAM_ADDR_FMT " bytes of ram at " RAM_ADDR_FMT " when runstate is INMIGRATE\n" , - __func__, size, ram_addr); + __func__, size, ram_addr);return ; }
hw/intc/ioapic.c +1 -1
@@ -89,7 +89,7 @@ static void ioapic_entry_parse(uint64_t entry, struct ioapic_entry_info *info)static void ioapic_service (IOAPICCommonState *s) { -AddressSpace *ioapic_as =PC_MACHINE (qdev_get_machine ())->ioapic_as; +AddressSpace *ioapic_as =X86_MACHINE (qdev_get_machine ())->ioapic_as;struct ioapic_entry_info info;uint8_t i;uint32_t mask;
Signature · 1 line
2.21.0
PATCH v10 9/15 hw/i386: make x86.c independent from PCMachineState
In reply to Sergio LopezAs a last step into splitting PCMachineState and deriving X86MachineState from it, make the functions previously extracted from pc.c to x86.c independent from PCMachineState, using X86MachineState instead.
--- include/hw/i386/x86.h | 13 +++++++---- hw/i386/pc.c | 14 ++++++++---- hw/i386/pc_piix.c | 2 +- hw/i386/pc_q35.c | 2 +- hw/i386/x86.c | 53 ++++++++++++++++++++----------------------- 5 files changed, 44 insertions(+), 40 deletions(-)
include/hw/i386/x86.h +9 -4
@@ -75,10 +75,11 @@ typedef struct {#define X86_MACHINE_CLASS (class) \ OBJECT_CLASS_CHECK(X86MachineClass, class, TYPE_X86_MACHINE) -uint32_t x86_cpu_apic_id_from_index (PCMachineState *pcms, +uint32_t x86_cpu_apic_id_from_index (X86MachineState *pcms,unsigned int cpu_index); -void x86_cpu_new (PCMachineState *pcms,int64_t apic_id,Error **errp); -void x86_cpus_init (PCMachineState *pcms); + +void x86_cpu_new (X86MachineState *pcms,int64_t apic_id,Error **errp); +void x86_cpus_init (X86MachineState *pcms,int default_cpu_version);CpuInstanceProperties x86_cpu_index_to_props (MachineState *ms,unsigned cpu_index);int64_t x86_get_default_cpu_node_id (const MachineState *ms,int idx);
@@ -86,6 +87,10 @@ const CPUArchIdList *x86_possible_cpu_arch_ids(MachineState *ms);void x86_bios_rom_init (MemoryRegion *rom_memory,bool isapc_ram_fw); -void x86_load_linux (PCMachineState *pcms,FWCfgState *fw_cfg); +void x86_load_linux (X86MachineState *x86ms, +FWCfgState *fw_cfg, +int acpi_data_size, +bool pvh_enabled, +bool linuxboot_dma_enabled);#endif
hw/i386/pc.c +9 -5
@@ -983,8 +983,8 @@ void pc_smp_parse(MachineState *ms, QemuOpts *opts)void pc_hot_add_cpu (MachineState *ms,const int64_t id,Error **errp) { -PCMachineState *pcms =PC_MACHINE (ms); -int64_t apic_id =x86_cpu_apic_id_from_index (pcms, id); +X86MachineState *x86ms =X86_MACHINE (ms); +int64_t apic_id =x86_cpu_apic_id_from_index (x86ms, id);Error *local_err =NULL ;if (id <0 ) {
@@ -999,7 +999,8 @@ void pc_hot_add_cpu(MachineState *ms, const int64_t id, Error **errp)return ; } -x86_cpu_new (PC_MACHINE (ms), apic_id, &local_err); + +x86_cpu_new (X86_MACHINE (ms), apic_id, &local_err);if (local_err) {error_propagate (errp, local_err);return ;
@@ -1100,6 +1101,7 @@ void xen_load_linux(PCMachineState *pcms) {int i;FWCfgState *fw_cfg; +PCMachineClass *pcmc =PC_MACHINE_GET_CLASS (pcms);X86MachineState *x86ms =X86_MACHINE (pcms);assert (MACHINE (pcms)->kernel_filename !=NULL );
@@ -1108,7 +1110,8 @@ void xen_load_linux(PCMachineState *pcms)fw_cfg_add_i16 (fw_cfg,FW_CFG_NB_CPUS , x86ms->boot_cpus);rom_set_fw (fw_cfg); -x86_load_linux (pcms, fw_cfg); +x86_load_linux (x86ms, fw_cfg, pcmc->acpi_data_size, + pcmc->pvh_enabled, pcmc->linuxboot_dma_enabled);for (i =0 ; i < nb_option_roms; i++) { assert(!strcmp(option_rom[i].name, "linuxboot.bin") || !strcmp(option_rom[i].name, "linuxboot_dma.bin") ||
@@ -1244,7 +1247,8 @@ void pc_memory_init(PCMachineState *pcms, }if (linux_boot) { -x86_load_linux (pcms, fw_cfg); +x86_load_linux (x86ms, fw_cfg, pcmc->acpi_data_size, + pcmc->pvh_enabled, pcmc->linuxboot_dma_enabled); }for (i =0 ; i < nb_option_roms; i++) {
hw/i386/pc_piix.c +1 -1
@@ -154,7 +154,7 @@ static void pc_init1(MachineState *machine, } } -x86_cpus_init (pcms); +x86_cpus_init (x86ms, pcmc->default_cpu_version);if (kvm_enabled () && pcmc->kvmclock_enabled) {kvmclock_create ();
hw/i386/pc_q35.c +1 -1
@@ -181,7 +181,7 @@ static void pc_q35_init(MachineState *machine)xen_hvm_init (pcms, &ram_memory); } -x86_cpus_init (pcms); +x86_cpus_init (x86ms, pcmc->default_cpu_version);kvmclock_create ();
hw/i386/x86.c +24 -29
147 lines not on this page · raw message
Signature · 1 line
2.21.0
PATCH v10 10/15 fw_cfg: add "modify" functions for all types
In reply to Sergio LopezThis allows to alter the contents of an already added item.
--- include/hw/nvram/fw_cfg.h | 42 +++++++++++++++++++++++++++++++++++++++ hw/nvram/fw_cfg.c | 29 +++++++++++++++++++++++++++ 2 files changed, 71 insertions(+)
include/hw/nvram/fw_cfg.h +42 -0
@@ -98,6 +98,20 @@ void fw_cfg_add_bytes(FWCfgState *s, uint16_t key, void *data, size_t len);*/ void fw_cfg_add_string (FWCfgState *s,uint16_t key,const char *value); +/** +* fw_cfg_modify_string: +* @s: fw_cfg device being modified +* @key: selector key value for new fw_cfg item +* @value: NUL-terminated ascii string +* +* Replace the fw_cfg item available by selecting the given key. The new +* data will consist of a dynamically allocated copy of the provided string, +* including its NUL terminator. The data being replaced, assumed to have +* been dynamically allocated during an earlier call to either +* fw_cfg_add_string() or fw_cfg_modify_string(), is freed before returning. +*/ +void fw_cfg_modify_string (FWCfgState *s,uint16_t key,const char *value); +/** * fw_cfg_add_i16: * @s: fw_cfg device being modified
@@ -136,6 +150,20 @@ void fw_cfg_modify_i16(FWCfgState *s, uint16_t key, uint16_t value);*/ void fw_cfg_add_i32 (FWCfgState *s,uint16_t key,uint32_t value); +/** +* fw_cfg_modify_i32: +* @s: fw_cfg device being modified +* @key: selector key value for new fw_cfg item +* @value: 32-bit integer +* +* Replace the fw_cfg item available by selecting the given key. The new +* data will consist of a dynamically allocated copy of the given 32-bit +* value, converted to little-endian representation. The data being replaced, +* assumed to have been dynamically allocated during an earlier call to +* either fw_cfg_add_i32() or fw_cfg_modify_i32(), is freed before returning. +*/ +void fw_cfg_modify_i32 (FWCfgState *s,uint16_t key,uint32_t value); +/** * fw_cfg_add_i64: * @s: fw_cfg device being modified
@@ -148,6 +176,20 @@ void fw_cfg_add_i32(FWCfgState *s, uint16_t key, uint32_t value);*/ void fw_cfg_add_i64 (FWCfgState *s,uint16_t key,uint64_t value); +/** +* fw_cfg_modify_i64: +* @s: fw_cfg device being modified +* @key: selector key value for new fw_cfg item +* @value: 64-bit integer +* +* Replace the fw_cfg item available by selecting the given key. The new +* data will consist of a dynamically allocated copy of the given 64-bit +* value, converted to little-endian representation. The data being replaced, +* assumed to have been dynamically allocated during an earlier call to +* either fw_cfg_add_i64() or fw_cfg_modify_i64(), is freed before returning. +*/ +void fw_cfg_modify_i64 (FWCfgState *s,uint16_t key,uint64_t value); +/** * fw_cfg_add_file: * @s: fw_cfg device being modified
hw/nvram/fw_cfg.c +29 -0
@@ -690,6 +690,15 @@ void fw_cfg_add_string(FWCfgState *s, uint16_t key, const char *value)fw_cfg_add_bytes (s, key,g_memdup (value, sz), sz); } +void fw_cfg_modify_string (FWCfgState *s,uint16_t key,const char *value) +{ +size_t sz =strlen (value) +1 ; +char *old; + + old =fw_cfg_modify_bytes_read (s, key,g_memdup (value, sz), sz); +g_free (old); +} +void fw_cfg_add_i16 (FWCfgState *s,uint16_t key,uint16_t value) {uint16_t *copy;
@@ -720,6 +729,16 @@ void fw_cfg_add_i32(FWCfgState *s, uint16_t key, uint32_t value)fw_cfg_add_bytes (s, key, copy,sizeof (value)); } +void fw_cfg_modify_i32 (FWCfgState *s,uint16_t key,uint32_t value) +{ +uint32_t *copy, *old; + + copy =g_malloc (sizeof (value)); + *copy =cpu_to_le32 (value); + old =fw_cfg_modify_bytes_read (s, key, copy,sizeof (value)); +g_free (old); +} +void fw_cfg_add_i64 (FWCfgState *s,uint16_t key,uint64_t value) {uint64_t *copy;
@@ -730,6 +749,16 @@ void fw_cfg_add_i64(FWCfgState *s, uint16_t key, uint64_t value)fw_cfg_add_bytes (s, key, copy,sizeof (value)); } +void fw_cfg_modify_i64 (FWCfgState *s,uint16_t key,uint64_t value) +{ +uint64_t *copy, *old; + + copy =g_malloc (sizeof (value)); + *copy =cpu_to_le64 (value); + old =fw_cfg_modify_bytes_read (s, key, copy,sizeof (value)); +g_free (old); +} +void fw_cfg_set_order_override (FWCfgState *s,int order) {assert (s->fw_cfg_order_override ==0 );
Signature · 1 line
2.21.0
Re: [PATCH v10 10/15] fw_cfg: add "modify" functions for all types
Quoted 5 lines · Sergio Lopez
This allows to alter the contents of an already added item.
Signed-off-by Sergio Lopez <[email protected]>Reviewed-by Michael S. Tsirkin <[email protected]>
Used to fix kernel command line in following patch "hw/i386: Introduce the microvm machine type", except fw_cfg_modify_i64().
Quoted 127 lines
--- include/hw/nvram/fw_cfg.h | 42 +++++++++++++++++++++++++++++++++++++++ hw/nvram/fw_cfg.c | 29 +++++++++++++++++++++++++++ 2 files changed, 71 insertions(+)include/hw/nvram/fw_cfg.h +42
-0@@ -98,6 +98,20 @@ void fw_cfg_add_bytes(FWCfgState *s, uint16_t key, void *data, size_t len);*/ void fw_cfg_add_string (FWCfgState *s,uint16_t key,const char *value); +/** +* fw_cfg_modify_string: +* @s: fw_cfg device being modified +* @key: selector key value for new fw_cfg item +* @value: NUL-terminated ascii string +* +* Replace the fw_cfg item available by selecting the given key. The new +* data will consist of a dynamically allocated copy of the provided string, +* including its NUL terminator. The data being replaced, assumed to have +* been dynamically allocated during an earlier call to either +* fw_cfg_add_string() or fw_cfg_modify_string(), is freed before returning. +*/ +void fw_cfg_modify_string (FWCfgState *s,uint16_t key,const char *value); +/** * fw_cfg_add_i16: * @s: fw_cfg device being modified @@ -136,6 +150,20 @@ void fw_cfg_modify_i16(FWCfgState *s, uint16_t key, uint16_t value);*/ void fw_cfg_add_i32 (FWCfgState *s,uint16_t key,uint32_t value); +/** +* fw_cfg_modify_i32: +* @s: fw_cfg device being modified +* @key: selector key value for new fw_cfg item +* @value: 32-bit integer +* +* Replace the fw_cfg item available by selecting the given key. The new +* data will consist of a dynamically allocated copy of the given 32-bit +* value, converted to little-endian representation. The data being replaced, +* assumed to have been dynamically allocated during an earlier call to +* either fw_cfg_add_i32() or fw_cfg_modify_i32(), is freed before returning. +*/ +void fw_cfg_modify_i32 (FWCfgState *s,uint16_t key,uint32_t value); +/** * fw_cfg_add_i64: * @s: fw_cfg device being modified @@ -148,6 +176,20 @@ void fw_cfg_add_i32(FWCfgState *s, uint16_t key, uint32_t value);*/ void fw_cfg_add_i64 (FWCfgState *s,uint16_t key,uint64_t value); +/** +* fw_cfg_modify_i64: +* @s: fw_cfg device being modified +* @key: selector key value for new fw_cfg item +* @value: 64-bit integer +* +* Replace the fw_cfg item available by selecting the given key. The new +* data will consist of a dynamically allocated copy of the given 64-bit +* value, converted to little-endian representation. The data being replaced, +* assumed to have been dynamically allocated during an earlier call to +* either fw_cfg_add_i64() or fw_cfg_modify_i64(), is freed before returning. +*/ +void fw_cfg_modify_i64 (FWCfgState *s,uint16_t key,uint64_t value); +/** * fw_cfg_add_file: * @s: fw_cfg device being modified hw/nvram/fw_cfg.c +29
-1@@ -690,6 +690,15 @@ void fw_cfg_add_string(FWCfgState *s, uint16_t key, const char *value)fw_cfg_add_bytes (s, key,g_memdup (value, sz), sz); } +void fw_cfg_modify_string (FWCfgState *s,uint16_t key,const char *value) +{ +size_t sz =strlen (value) +1 ; +char *old; + + old =fw_cfg_modify_bytes_read (s, key,g_memdup (value, sz), sz); +g_free (old); +} +void fw_cfg_add_i16 (FWCfgState *s,uint16_t key,uint16_t value) {uint16_t *copy;@@ -720,6 +729,16 @@ void fw_cfg_add_i32(FWCfgState *s, uint16_t key, uint32_t value)fw_cfg_add_bytes (s, key, copy,sizeof (value)); } +void fw_cfg_modify_i32 (FWCfgState *s,uint16_t key,uint32_t value) +{ +uint32_t *copy, *old; + + copy =g_malloc (sizeof (value)); + *copy =cpu_to_le32 (value); + old =fw_cfg_modify_bytes_read (s, key, copy,sizeof (value)); +g_free (old); +} +void fw_cfg_add_i64 (FWCfgState *s,uint16_t key,uint64_t value) {uint64_t *copy;@@ -730,6 +749,16 @@ void fw_cfg_add_i64(FWCfgState *s, uint16_t key, uint64_t value)fw_cfg_add_bytes (s, key, copy,sizeof (value)); } +void fw_cfg_modify_i64 (FWCfgState *s,uint16_t key,uint64_t value) +{ +uint64_t *copy, *old; + + copy =g_malloc (sizeof (value)); + *copy =cpu_to_le64 (value); + old =fw_cfg_modify_bytes_read (s, key, copy,sizeof (value)); +g_free (old); +} +void fw_cfg_set_order_override (FWCfgState *s,int order) {assert (s->fw_cfg_order_override ==0 ); --
Quoted 3 lines
2.21.0
--
Marc-André Lureau
PATCH v10 11/15 hw/intc/apic: reject pic ints if isa_pic == NULL
In reply to Sergio LopezIn apic_accept_pic_intr(), reject PIC interruptions if a i8259 PIC has not been instantiated (isa_pic == NULL).
--- hw/intc/apic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
hw/intc/apic.c +1 -1
@@ -610,7 +610,7 @@ int apic_accept_pic_intr(DeviceState *dev)if ((s->apicbase &MSR_IA32_APICBASE_ENABLE ) ==0 || (lvt0 &APIC_LVT_MASKED ) ==0 ) -return 1 ; +return isa_pic !=NULL ;return 0 ; }
Signature · 1 line
2.21.0
PATCH v10 12/15 roms: add microvm-bios (qboot) as binary and git submodule
In reply to Sergio Lopezqboot is a minimalist x86 firmware for booting Linux kernels. It does the mininum amount of work required for the task, and it's able to boot both PVH images and bzImages without relying on option roms.
This characteristics make it an ideal companion for the microvm machine type.
--- .gitmodules | 3 +++ pc-bios/bios-microvm.bin | Bin 0 -> 65536 bytes roms/Makefile | 6 ++++++ roms/qboot | 1 + 4 files changed, 10 insertions(+) create mode 100644 pc-bios/bios-microvm.bin create mode 160000 roms/qboot
.gitmodules +3 -0
@@ -58,3 +58,6 @@ [submodule "roms/opensbi"] path = roms/opensbi url = https://git.qemu.org/git/opensbi.git +[submodule "roms/qboot"] + path = roms/qboot + url = https://github.com/bonzini/qboot
pc-bios/bios-microvm.bin new file binary +0 -0
roms/Makefile +6 -0
@@ -67,6 +67,7 @@ default help: @echo " opensbi32-virt -- update OpenSBI for 32-bit virt machine" @echo " opensbi64-virt -- update OpenSBI for 64-bit virt machine" @echo " opensbi64-sifive_u -- update OpenSBI for 64-bit sifive_u machine" + @echo " bios-microvm -- update bios-microvm.bin (qboot)" @echo " clean -- delete the files generated by the previous" \ "build targets"
@@ -186,6 +187,10 @@ opensbi64-sifive_u: PLATFORM="sifive/fu540" cp opensbi/build/platform/sifive/fu540/firmware/fw_jump.bin ../pc-bios/opensbi-riscv64-sifive_u-fw_jump.bin +bios-microvm: + $(MAKE) -C qboot + cp qboot/bios.bin ../pc-bios/bios-microvm.bin + clean: rm -rf seabios/.config seabios/out seabios/builds $(MAKE) -C sgabios clean
@@ -198,3 +203,4 @@ clean: $(MAKE) -C skiboot clean $(MAKE) -f Makefile.edk2 clean $(MAKE) -C opensbi clean + $(MAKE) -C qboot clean
roms/qboot new file +1 -0
@@ -0,0 +1 @@ +Subproject commit cb1c49e0cfac99b9961d136ac0194da62c28cf64
Signature · 1 line
2.21.0
PATCH v10 13/15 docs/microvm.rst: document the new microvm machine type
In reply to Sergio LopezDocument the new microvm machine type.
--- docs/microvm.rst | 98 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 docs/microvm.rst
docs/microvm.rst new file +98 -0
@@ -0,0 +1,98 @@ +==================== +microvm Machine Type +==================== + +``microvm`` is a machine type inspired by ``Firecracker`` and +constructed after its machine model. + +It's a minimalist machine type without ``PCI`` nor ``ACPI`` support, +designed for short-lived guests. microvm also establishes a baseline +for benchmarking and optimizing both QEMU and guest operating systems, +since it is optimized for both boot time and footprint. + + +Supported devices +----------------- + +The microvm machine type supports the following devices: + +- ISA bus +- i8259 PIC (optional) +- i8254 PIT (optional) +- MC146818 RTC (optional) +- One ISA serial port (optional) +- LAPIC +- IOAPIC (with kernel-irqchip=split by default) +- kvmclock (if using KVM) +- fw_cfg +- Up to eight virtio-mmio devices (configured by the user) + + +Using the microvm machine type +------------------------------ + +Machine-specific options +~~~~~~~~~~~~~~~~~~~~~~~~ + +It supports the following machine-specific options: + +- microvm.x-option-roms=bool (Set off to disable loading option ROMs) +- microvm.pit=OnOffAuto (Enable i8254 PIT) +- microvm.isa-serial=bool (Set off to disable the instantiation an ISA serial port) +- microvm.pic=OnOffAuto (Enable i8259 PIC) +- microvm.rtc=OnOffAuto (Enable MC146818 RTC) +- microvm.auto-kernel-cmdline=bool (Set off to disable adding virtio-mmio devices to the kernel cmdline) + + +Boot options +~~~~~~~~~~~~ + +By default, microvm uses ``qboot`` as its BIOS, to obtain better boot +times, but it's also compatible with ``SeaBIOS``. + +As no current FW is able to boot from a block device using +``virtio-mmio`` as its transport, a microvm-based VM needs to be run +using a host-side kernel and, optionally, an initrd image. + + +Running a microvm-based VM +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +By default, microvm aims for maximum compatibility, enabling both +legacy and non-legacy devices. In this example, a VM is created +without passing any additional machine-specific option, using the +legacy ``ISA serial`` device as console:: + + $ qemu-system-x86_64 -M microvm \ + -enable-kvm -cpu host -m 512m -smp 2 \ + -kernel vmlinux -append "earlyprintk=ttyS0 console=ttyS0 root=/dev/vda" \ + -nodefaults -no-user-config -nographic \ + -serial stdio \ + -drive id=test,file=test.img,format=raw,if=none \ + -device virtio-blk-device,drive=test \ + -netdev tap,id=tap0,script=no,downscript=no \ + -device virtio-net-device,netdev=tap0 + +While the example above works, you might be interested in reducing the +footprint further by disabling some legacy devices. If you're using +``KVM``, you can disable the ``RTC``, making the Guest rely on +``kvmclock`` exclusively. Additionally, if your host's CPUs have the +``TSC_DEADLINE`` feature, you can also disable both the i8259 PIC and +the i8254 PIT (make sure you're also emulating a CPU with such feature +in the guest). + +This is an example of a VM with all optional legacy features +disabled:: + + $ qemu-system-x86_64 \ + -M microvm,x-option-roms=off,pit=off,pic=off,isa-serial=off,rtc=off \ + -enable-kvm -cpu host -m 512m -smp 2 \ + -kernel vmlinux -append "console=hvc0 root=/dev/vda" \ + -nodefaults -no-user-config -nographic \ + -chardev stdio,id=virtiocon0,server \ + -device virtio-serial-device \ + -device virtconsole,chardev=virtiocon0 \ + -drive id=test,file=test.img,format=raw,if=none \ + -device virtio-blk-device,drive=test \ + -netdev tap,id=tap0,script=no,downscript=no \ + -device virtio-net-device,netdev=tap0
Signature · 1 line
2.21.0
Re: [PATCH v10 13/15] docs/microvm.rst: document the new microvm machine type
Hi
Quoted 98 lines · Sergio Lopez
Document the new microvm machine type.
Signed-off-by Sergio Lopez <[email protected]>Reviewed-by Michael S. Tsirkin <[email protected]>--- docs/microvm.rst | 98 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 docs/microvm.rstdocs/microvm.rst new file +82
-0@@ -0,0 +1,98 @@ +==================== +microvm Machine Type +==================== + +``microvm`` is a machine type inspired by ``Firecracker`` and +constructed after its machine model. + +It's a minimalist machine type without ``PCI`` nor ``ACPI`` support, +designed for short-lived guests. microvm also establishes a baseline +for benchmarking and optimizing both QEMU and guest operating systems, +since it is optimized for both boot time and footprint. + + +Supported devices +----------------- + +The microvm machine type supports the following devices: + +- ISA bus +- i8259 PIC (optional) +- i8254 PIT (optional) +- MC146818 RTC (optional) +- One ISA serial port (optional) +- LAPIC +- IOAPIC (with kernel-irqchip=split by default) +- kvmclock (if using KVM) +- fw_cfg +- Up to eight virtio-mmio devices (configured by the user) + + +Using the microvm machine type +------------------------------ + +Machine-specific options +~~~~~~~~~~~~~~~~~~~~~~~~ + +It supports the following machine-specific options: + +- microvm.x-option-roms=bool (Set off to disable loading option ROMs) +- microvm.pit=OnOffAuto (Enable i8254 PIT) +- microvm.isa-serial=bool (Set off to disable the instantiation an ISA serial port) +- microvm.pic=OnOffAuto (Enable i8259 PIC) +- microvm.rtc=OnOffAuto (Enable MC146818 RTC) +- microvm.auto-kernel-cmdline=bool (Set off to disable adding virtio-mmio devices to the kernel cmdline) + + +Boot options +~~~~~~~~~~~~ + +By default, microvm uses ``qboot`` as its BIOS, to obtain better boot +times, but it's also compatible with ``SeaBIOS``. + +As no current FW is able to boot from a block device using +``virtio-mmio`` as its transport, a microvm-based VM needs to be run +using a host-side kernel and, optionally, an initrd image. + + +Running a microvm-based VM +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +By default, microvm aims for maximum compatibility, enabling both +legacy and non-legacy devices. In this example, a VM is created +without passing any additional machine-specific option, using the +legacy ``ISA serial`` device as console:: + + $ qemu-system-x86_64 -M microvm \ + -enable-kvm -cpu host -m 512m -smp 2 \ + -kernel vmlinux -append "earlyprintk=ttyS0 console=ttyS0 root=/dev/vda" \ + -nodefaults -no-user-config -nographic \ + -serial stdio \ + -drive id=test,file=test.img,format=raw,if=none \ + -device virtio-blk-device,drive=test \ + -netdev tap,id=tap0,script=no,downscript=no \ + -device virtio-net-device,netdev=tap0 + +While the example above works, you might be interested in reducing the +footprint further by disabling some legacy devices. If you're using +``KVM``, you can disable the ``RTC``, making the Guest rely on +``kvmclock`` exclusively. Additionally, if your host's CPUs have the +``TSC_DEADLINE`` feature, you can also disable both the i8259 PIC and +the i8254 PIT (make sure you're also emulating a CPU with such feature +in the guest).
docs/microvm.rst line 92
Quoted 10 lines
docs/microvm.rst new file +10
-0+ +This is an example of a VM with all optional legacy features +disabled:: + + $ qemu-system-x86_64 \ + -M microvm,x-option-roms=off,pit=off,pic=off,isa-serial=off,rtc=off \ + -enable-kvm -cpu host -m 512m -smp 2 \ + -kernel vmlinux -append "console=hvc0 root=/dev/vda" \ + -nodefaults -no-user-config -nographic \ + -chardev stdio,id=virtiocon0,server \
server? doesn't make sense here :)
Quoted 10 lines
docs/microvm.rst new file +6
-1+ -device virtio-serial-device \ + -device virtconsole,chardev=virtiocon0 \ + -drive id=test,file=test.img,format=raw,if=none \ + -device virtio-blk-device,drive=test \ + -netdev tap,id=tap0,script=no,downscript=no \ + -device virtio-net-device,netdev=tap0 --2.21.0
seem to work with appropriate kernel otherwise, so
Signature · 1 line
Marc-André Lureau
Re: [PATCH v10 13/15] docs/microvm.rst: document the new microvm machine type
Quoted 105 lines · Marc-André Lureau
Hi
Quoted 102 lines · Sergio Lopez
Document the new microvm machine type.
Signed-off-by Sergio Lopez <[email protected]>Reviewed-by Michael S. Tsirkin <[email protected]>--- docs/microvm.rst | 98 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 docs/microvm.rstdocs/microvm.rst new file +86
-0@@ -0,0 +1,98 @@ +==================== +microvm Machine Type +==================== + +``microvm`` is a machine type inspired by ``Firecracker`` and +constructed after its machine model. + +It's a minimalist machine type without ``PCI`` nor ``ACPI`` support, +designed for short-lived guests. microvm also establishes a baseline +for benchmarking and optimizing both QEMU and guest operating systems, +since it is optimized for both boot time and footprint. + + +Supported devices +----------------- + +The microvm machine type supports the following devices: + +- ISA bus +- i8259 PIC (optional) +- i8254 PIT (optional) +- MC146818 RTC (optional) +- One ISA serial port (optional) +- LAPIC +- IOAPIC (with kernel-irqchip=split by default) +- kvmclock (if using KVM) +- fw_cfg +- Up to eight virtio-mmio devices (configured by the user) + + +Using the microvm machine type +------------------------------ + +Machine-specific options +~~~~~~~~~~~~~~~~~~~~~~~~ + +It supports the following machine-specific options: + +- microvm.x-option-roms=bool (Set off to disable loading option ROMs) +- microvm.pit=OnOffAuto (Enable i8254 PIT) +- microvm.isa-serial=bool (Set off to disable the instantiation an ISA serial port) +- microvm.pic=OnOffAuto (Enable i8259 PIC) +- microvm.rtc=OnOffAuto (Enable MC146818 RTC) +- microvm.auto-kernel-cmdline=bool (Set off to disable adding virtio-mmio devices to the kernel cmdline) + + +Boot options +~~~~~~~~~~~~ + +By default, microvm uses ``qboot`` as its BIOS, to obtain better boot +times, but it's also compatible with ``SeaBIOS``. + +As no current FW is able to boot from a block device using +``virtio-mmio`` as its transport, a microvm-based VM needs to be run +using a host-side kernel and, optionally, an initrd image. + + +Running a microvm-based VM +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +By default, microvm aims for maximum compatibility, enabling both +legacy and non-legacy devices. In this example, a VM is created +without passing any additional machine-specific option, using the +legacy ``ISA serial`` device as console:: + + $ qemu-system-x86_64 -M microvm \ + -enable-kvm -cpu host -m 512m -smp 2 \ + -kernel vmlinux -append "earlyprintk=ttyS0 console=ttyS0 root=/dev/vda" \ + -nodefaults -no-user-config -nographic \ + -serial stdio \ + -drive id=test,file=test.img,format=raw,if=none \ + -device virtio-blk-device,drive=test \ + -netdev tap,id=tap0,script=no,downscript=no \ + -device virtio-net-device,netdev=tap0 + +While the example above works, you might be interested in reducing the +footprint further by disabling some legacy devices. If you're using +``KVM``, you can disable the ``RTC``, making the Guest rely on +``kvmclock`` exclusively. Additionally, if your host's CPUs have the +``TSC_DEADLINE`` feature, you can also disable both the i8259 PIC and +the i8254 PIT (make sure you're also emulating a CPU with such feature +in the guest). + +This is an example of a VM with all optional legacy features +disabled:: +
Quoted 8 lines
docs/microvm.rst line 92
Quoted 6 lines
docs/microvm.rst new file +6
-0+ $ qemu-system-x86_64 \ + -M microvm,x-option-roms=off,pit=off,pic=off,isa-serial=off,rtc=off \ + -enable-kvm -cpu host -m 512m -smp 2 \ + -kernel vmlinux -append "console=hvc0 root=/dev/vda" \ + -nodefaults -no-user-config -nographic \ + -chardev stdio,id=virtiocon0,server \server? doesn't make sense here :)
Heh, good catch!
Thanks,
Sergio.
Quoted 13 lines
Quoted 10 lines
docs/microvm.rst new file +6
-1+ -device virtio-serial-device \ + -device virtconsole,chardev=virtiocon0 \ + -drive id=test,file=test.img,format=raw,if=none \ + -device virtio-blk-device,drive=test \ + -netdev tap,id=tap0,script=no,downscript=no \ + -device virtio-net-device,netdev=tap0 --2.21.0
seem to work with appropriate kernel otherwise, so
Reviewed-by Marc-André Lureau <[email protected]>
Re: [PATCH v10 13/15] docs/microvm.rst: document the new microvm machine type
In reply to Sergio LopezHi Sergio,
Quoted 5 lines · Sergio Lopez
docs/microvm.rst new file +5
-0+Supported devices +----------------- + +The microvm machine type supports the following devices: +
docs/microvm.rst line 28
Quoted 10 lines
docs/microvm.rst new file +10
-0+- ISA bus +- i8259 PIC (optional) +- i8254 PIT (optional) +- MC146818 RTC (optional) +- One ISA serial port (optional) +- LAPIC +- IOAPIC (with kernel-irqchip=split by default) +- kvmclock (if using KVM) +- fw_cfg +- Up to eight virtio-mmio devices (configured by the user)
If we have VirtIO devices, why not use virtio-serial instead of the one on the ISA bus?
Re: [PATCH v10 13/15] docs/microvm.rst: document the new microvm machine type
Quoted 13 lines · Philippe Mathieu-Daudé
Hi Sergio,
Quoted 10 lines · Sergio Lopez
docs/microvm.rst new file +10
-0+Supported devices +----------------- + +The microvm machine type supports the following devices: + +- ISA bus +- i8259 PIC (optional) +- i8254 PIT (optional) +- MC146818 RTC (optional) +- One ISA serial port (optional)
Quoted 8 lines
Quoted 5 lines
+- LAPIC +- IOAPIC (with kernel-irqchip=split by default) +- kvmclock (if using KVM) +- fw_cfg +- Up to eight virtio-mmio devices (configured by the user)If we have VirtIO devices, why not use virtio-serial instead of the one on the ISA bus?
The serial port on the ISA bus is simpler, and thus is supported for both SeaBIOS debugging and Linux's earlyprintk. This makes it *very* convenient for debugging boot issues.
Also, as it's explained in the documentation, users that no longer need it can disable the device and just rely on virtio-console.
Sergio.
Re: [PATCH v10 13/15] docs/microvm.rst: document the new microvm machine type
Quoted 25 lines · Sergio Lopez
Quoted 13 lines · Philippe Mathieu-Daudé
Hi Sergio,
Quoted 10 lines · Sergio Lopez
docs/microvm.rst new file +10
-0+Supported devices +----------------- + +The microvm machine type supports the following devices: + +- ISA bus +- i8259 PIC (optional) +- i8254 PIT (optional) +- MC146818 RTC (optional) +- One ISA serial port (optional)Quoted 8 lines
Quoted 5 lines
+- LAPIC +- IOAPIC (with kernel-irqchip=split by default) +- kvmclock (if using KVM) +- fw_cfg +- Up to eight virtio-mmio devices (configured by the user)If we have VirtIO devices, why not use virtio-serial instead of the one on the ISA bus?
Quoted 3 lines
The serial port on the ISA bus is simpler, and thus is supported for both SeaBIOS debugging and Linux's earlyprintk. This makes it *very* convenient for debugging boot issues.
"... but it's also compatible with SeaBIOS"
OK. Maybe we can add a comment such "These devices are the minimum required to run SeaBIOS" in the 'Supported devices' section.
Quoted 6 lines
Also, as it's explained in the documentation, users that no longer need it can disable the device and just rely on virtio-console.
Sergio.
Re: [PATCH v10 13/15] docs/microvm.rst: document the new microvm machine type
Quoted 26 lines · Philippe Mathieu-Daudé
Quoted 25 lines · Sergio Lopez
Quoted 21 lines · Philippe Mathieu-Daudé
Hi Sergio,
Quoted 5 lines · Sergio Lopez
docs/microvm.rst new file +5
-0+Supported devices +----------------- + +The microvm machine type supports the following devices: +docs/microvm.rst line 28
Quoted 10 lines
docs/microvm.rst new file +10
-0+- ISA bus +- i8259 PIC (optional) +- i8254 PIT (optional) +- MC146818 RTC (optional) +- One ISA serial port (optional) +- LAPIC +- IOAPIC (with kernel-irqchip=split by default) +- kvmclock (if using KVM) +- fw_cfg +- Up to eight virtio-mmio devices (configured by the user)If we have VirtIO devices, why not use virtio-serial instead of the one on the ISA bus?
Quoted 8 lines
Quoted 3 lines
The serial port on the ISA bus is simpler, and thus is supported for both SeaBIOS debugging and Linux's earlyprintk. This makes it *very* convenient for debugging boot issues.
"... but it's also compatible with SeaBIOS"
OK. Maybe we can add a comment such "These devices are the minimum required to run SeaBIOS" in the 'Supported devices' section.
Well, that's not exactly true. SeaBIOS works without a serial port, it's just you can't get it to send its debugging messages anywhere (which most people won't see anyway).
Sergio.
Quoted 6 lines
Quoted 6 lines
Also, as it's explained in the documentation, users that no longer need it can disable the device and just rely on virtio-console.
Sergio.
Re: [PATCH v10 13/15] docs/microvm.rst: document the new microvm machine type
In reply to Sergio LopezQuoted 16 lines · Sergio Lopez
Document the new microvm machine type.
Signed-off-by Sergio Lopez <[email protected]>Reviewed-by Michael S. Tsirkin <[email protected]>--- docs/microvm.rst | 98 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 docs/microvm.rstdocs/microvm.rst new file +1
-0@@ -0,0 +1,98 @@ +====================
docs/microvm.rst line 11
Quoted 10 lines
docs/microvm.rst new file +10
-0+microvm Machine Type +==================== + +``microvm`` is a machine type inspired by ``Firecracker`` and +constructed after its machine model. + +It's a minimalist machine type without ``PCI`` nor ``ACPI`` support, +designed for short-lived guests. microvm also establishes a baseline +for benchmarking and optimizing both QEMU and guest operating systems, +since it is optimized for both boot time and footprint.
I'm wondering about live migration support across QEMU versions.
IIUC, this is not intended to be a versioned machined type, so live migration won't be supportable across QEMU versions.
Given that its for short lived guests, this shouldn't be an issue, but it might be worth saying something explicit here about migration to avoid any risk of misunderstanding.
Quoted 91 lines
docs/microvm.rst new file +87
-0+ + +Supported devices +----------------- + +The microvm machine type supports the following devices: + +- ISA bus +- i8259 PIC (optional) +- i8254 PIT (optional) +- MC146818 RTC (optional) +- One ISA serial port (optional) +- LAPIC +- IOAPIC (with kernel-irqchip=split by default) +- kvmclock (if using KVM) +- fw_cfg +- Up to eight virtio-mmio devices (configured by the user) + + +Using the microvm machine type +------------------------------ + +Machine-specific options +~~~~~~~~~~~~~~~~~~~~~~~~ + +It supports the following machine-specific options: + +- microvm.x-option-roms=bool (Set off to disable loading option ROMs) +- microvm.pit=OnOffAuto (Enable i8254 PIT) +- microvm.isa-serial=bool (Set off to disable the instantiation an ISA serial port) +- microvm.pic=OnOffAuto (Enable i8259 PIC) +- microvm.rtc=OnOffAuto (Enable MC146818 RTC) +- microvm.auto-kernel-cmdline=bool (Set off to disable adding virtio-mmio devices to the kernel cmdline) + + +Boot options +~~~~~~~~~~~~ + +By default, microvm uses ``qboot`` as its BIOS, to obtain better boot +times, but it's also compatible with ``SeaBIOS``. + +As no current FW is able to boot from a block device using +``virtio-mmio`` as its transport, a microvm-based VM needs to be run +using a host-side kernel and, optionally, an initrd image. + + +Running a microvm-based VM +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +By default, microvm aims for maximum compatibility, enabling both +legacy and non-legacy devices. In this example, a VM is created +without passing any additional machine-specific option, using the +legacy ``ISA serial`` device as console:: + + $ qemu-system-x86_64 -M microvm \ + -enable-kvm -cpu host -m 512m -smp 2 \ + -kernel vmlinux -append "earlyprintk=ttyS0 console=ttyS0 root=/dev/vda" \ + -nodefaults -no-user-config -nographic \ + -serial stdio \ + -drive id=test,file=test.img,format=raw,if=none \ + -device virtio-blk-device,drive=test \ + -netdev tap,id=tap0,script=no,downscript=no \ + -device virtio-net-device,netdev=tap0 + +While the example above works, you might be interested in reducing the +footprint further by disabling some legacy devices. If you're using +``KVM``, you can disable the ``RTC``, making the Guest rely on +``kvmclock`` exclusively. Additionally, if your host's CPUs have the +``TSC_DEADLINE`` feature, you can also disable both the i8259 PIC and +the i8254 PIT (make sure you're also emulating a CPU with such feature +in the guest). + +This is an example of a VM with all optional legacy features +disabled:: + + $ qemu-system-x86_64 \ + -M microvm,x-option-roms=off,pit=off,pic=off,isa-serial=off,rtc=off \ + -enable-kvm -cpu host -m 512m -smp 2 \ + -kernel vmlinux -append "console=hvc0 root=/dev/vda" \ + -nodefaults -no-user-config -nographic \ + -chardev stdio,id=virtiocon0,server \ + -device virtio-serial-device \ + -device virtconsole,chardev=virtiocon0 \ + -drive id=test,file=test.img,format=raw,if=none \ + -device virtio-blk-device,drive=test \ + -netdev tap,id=tap0,script=no,downscript=no \ + -device virtio-net-device,netdev=tap0Signature · 1 line
2.21.0
Regards,
Daniel
Signature · 3 lines
|: https://berrange.com -o- https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o- https://fstop138.berrange.com :| |: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|
Re: [PATCH v10 13/15] docs/microvm.rst: document the new microvm machine type
Quoted 30 lines · Daniel P. Berrangé
Quoted 16 lines · Sergio Lopez
Document the new microvm machine type.
Signed-off-by Sergio Lopez <[email protected]>Reviewed-by Michael S. Tsirkin <[email protected]>--- docs/microvm.rst | 98 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 docs/microvm.rstdocs/microvm.rst new file +1
-0@@ -0,0 +1,98 @@ +====================docs/microvm.rst line 11
Quoted 10 lines
docs/microvm.rst new file +10
-0+microvm Machine Type +==================== + +``microvm`` is a machine type inspired by ``Firecracker`` and +constructed after its machine model. + +It's a minimalist machine type without ``PCI`` nor ``ACPI`` support, +designed for short-lived guests. microvm also establishes a baseline +for benchmarking and optimizing both QEMU and guest operating systems, +since it is optimized for both boot time and footprint.I'm wondering about live migration support across QEMU versions.
Quoted 6 lines
IIUC, this is not intended to be a versioned machined type, so live migration won't be supportable across QEMU versions.
Given that its for short lived guests, this shouldn't be an issue, but it might be worth saying something explicit here about migration to avoid any risk of misunderstanding.
It may be worth adding a Limitations section. Something like this:
Limitations
-----------
Currently, microvm does *not* support the following features:
- PCI-only devices.
- Hotplug of any kind.
- Live migration across QEMU versions.
Any other thing we should highlight there?
Thanks,
Sergio.
Quoted 94 lines
Quoted 91 lines
docs/microvm.rst new file +87
-0+ + +Supported devices +----------------- + +The microvm machine type supports the following devices: + +- ISA bus +- i8259 PIC (optional) +- i8254 PIT (optional) +- MC146818 RTC (optional) +- One ISA serial port (optional) +- LAPIC +- IOAPIC (with kernel-irqchip=split by default) +- kvmclock (if using KVM) +- fw_cfg +- Up to eight virtio-mmio devices (configured by the user) + + +Using the microvm machine type +------------------------------ + +Machine-specific options +~~~~~~~~~~~~~~~~~~~~~~~~ + +It supports the following machine-specific options: + +- microvm.x-option-roms=bool (Set off to disable loading option ROMs) +- microvm.pit=OnOffAuto (Enable i8254 PIT) +- microvm.isa-serial=bool (Set off to disable the instantiation an ISA serial port) +- microvm.pic=OnOffAuto (Enable i8259 PIC) +- microvm.rtc=OnOffAuto (Enable MC146818 RTC) +- microvm.auto-kernel-cmdline=bool (Set off to disable adding virtio-mmio devices to the kernel cmdline) + + +Boot options +~~~~~~~~~~~~ + +By default, microvm uses ``qboot`` as its BIOS, to obtain better boot +times, but it's also compatible with ``SeaBIOS``. + +As no current FW is able to boot from a block device using +``virtio-mmio`` as its transport, a microvm-based VM needs to be run +using a host-side kernel and, optionally, an initrd image. + + +Running a microvm-based VM +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +By default, microvm aims for maximum compatibility, enabling both +legacy and non-legacy devices. In this example, a VM is created +without passing any additional machine-specific option, using the +legacy ``ISA serial`` device as console:: + + $ qemu-system-x86_64 -M microvm \ + -enable-kvm -cpu host -m 512m -smp 2 \ + -kernel vmlinux -append "earlyprintk=ttyS0 console=ttyS0 root=/dev/vda" \ + -nodefaults -no-user-config -nographic \ + -serial stdio \ + -drive id=test,file=test.img,format=raw,if=none \ + -device virtio-blk-device,drive=test \ + -netdev tap,id=tap0,script=no,downscript=no \ + -device virtio-net-device,netdev=tap0 + +While the example above works, you might be interested in reducing the +footprint further by disabling some legacy devices. If you're using +``KVM``, you can disable the ``RTC``, making the Guest rely on +``kvmclock`` exclusively. Additionally, if your host's CPUs have the +``TSC_DEADLINE`` feature, you can also disable both the i8259 PIC and +the i8254 PIT (make sure you're also emulating a CPU with such feature +in the guest). + +This is an example of a VM with all optional legacy features +disabled:: + + $ qemu-system-x86_64 \ + -M microvm,x-option-roms=off,pit=off,pic=off,isa-serial=off,rtc=off \ + -enable-kvm -cpu host -m 512m -smp 2 \ + -kernel vmlinux -append "console=hvc0 root=/dev/vda" \ + -nodefaults -no-user-config -nographic \ + -chardev stdio,id=virtiocon0,server \ + -device virtio-serial-device \ + -device virtconsole,chardev=virtiocon0 \ + -drive id=test,file=test.img,format=raw,if=none \ + -device virtio-blk-device,drive=test \ + -netdev tap,id=tap0,script=no,downscript=no \ + -device virtio-net-device,netdev=tap0Signature · 1 line
2.21.0Regards,
Daniel
PATCH v10 14/15 hw/i386: Introduce the microvm machine type
In reply to Sergio Lopezmicrovm is a machine type inspired by Firecracker and constructed after its machine model.
It's a minimalist machine type without PCI nor ACPI support, designed for short-lived guests. microvm also establishes a baseline for benchmarking and optimizing both QEMU and guest operating systems, since it is optimized for both boot time and footprint.
--- default-configs/i386-softmmu.mak | 1 + include/hw/i386/microvm.h | 83 +++++ hw/i386/microvm.c | 572 +++++++++++++++++++++++++++++++ hw/i386/Kconfig | 10 + hw/i386/Makefile.objs | 1 + 5 files changed, 667 insertions(+) create mode 100644 include/hw/i386/microvm.h create mode 100644 hw/i386/microvm.c
default-configs/i386-softmmu.mak +1 -0
@@ -28,3 +28,4 @@ CONFIG_ISAPC=y CONFIG_I440FX=y CONFIG_Q35=y +CONFIG_MICROVM=y
include/hw/i386/microvm.h new file +83 -0
83 lines not on this page · raw message
hw/i386/microvm.c new file +572 -0
572 lines not on this page · raw message
hw/i386/Kconfig +10 -0
@@ -92,6 +92,16 @@ config Q35 select SMBIOS select FW_CFG_DMA +config MICROVM + bool + imply SERIAL_ISA + select ISA_BUS + select APIC + select IOAPIC + select I8259 + select MC146818RTC + select VIRTIO_MMIO + config VTD bool
hw/i386/Makefile.objs +1 -0
@@ -4,6 +4,7 @@ obj-y += x86.o obj-y += pc.o obj-$(CONFIG_I440FX) += pc_piix.o obj-$(CONFIG_Q35) += pc_q35.o +obj-$(CONFIG_MICROVM) += microvm.o obj-y += fw_cfg.o pc_sysfw.o obj-y += x86-iommu.o obj-$(CONFIG_VTD) += intel_iommu.o
Signature · 1 line
2.21.0
Re: [PATCH v10 14/15] hw/i386: Introduce the microvm machine type
Hi
Quoted 64 lines · Sergio Lopez
microvm is a machine type inspired by Firecracker and constructed after its machine model.
It's a minimalist machine type without PCI nor ACPI support, designed for short-lived guests. microvm also establishes a baseline for benchmarking and optimizing both QEMU and guest operating systems, since it is optimized for both boot time and footprint.
Signed-off-by Sergio Lopez <[email protected]>Reviewed-by Michael S. Tsirkin <[email protected]>--- default-configs/i386-softmmu.mak | 1 + include/hw/i386/microvm.h | 83 +++++ hw/i386/microvm.c | 572 +++++++++++++++++++++++++++++++ hw/i386/Kconfig | 10 + hw/i386/Makefile.objs | 1 + 5 files changed, 667 insertions(+) create mode 100644 include/hw/i386/microvm.h create mode 100644 hw/i386/microvm.cdefault-configs/i386-softmmu.mak +1
-0@@ -28,3 +28,4 @@ CONFIG_ISAPC=y CONFIG_I440FX=y CONFIG_Q35=y +CONFIG_MICROVM=yinclude/hw/i386/microvm.h new file +28
-0@@ -0,0 +1,83 @@ +/* +* Copyright (c) 2018 Intel Corporation +* Copyright (c) 2019 Red Hat, Inc. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2 or later, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef HW_I386_MICROVM_H +#define HW_I386_MICROVM_H + +#include "qemu-common.h" +#include "exec/hwaddr.h" +#include "qemu/notify.h" + +#include "hw/boards.h" +#include "hw/i386/x86.h" + +/* microvm memory layout */
include/hw/i386/microvm.h line 38
Quoted 10 lines
include/hw/i386/microvm.h new file +10
-0+#define PVH_START_INFO 0x6000 +#define MEMMAP_START 0x7000 +#define MODLIST_START 0x7800 +#define BOOT_STACK_POINTER 0x8ff0 +#define PML4_START 0x9000 +#define PDPTE_START 0xa000 +#define PDE_START 0xb000 +#define KERNEL_CMDLINE_START 0x20000 +#define EBDA_START 0x9fc00 +#define HIMEM_START 0x100000
Those define looks outdated, or am I missing something?
Quoted 660 lines
include/hw/i386/microvm.h new file +45
-0+ +/* Platform virtio definitions */ +#define VIRTIO_MMIO_BASE 0xc0000000 +#define VIRTIO_IRQ_BASE 5 +#define VIRTIO_NUM_TRANSPORTS 8 +#define VIRTIO_CMDLINE_MAXLEN 64 + +/* Machine type options */ +#define MICROVM_MACHINE_PIT "pit" +#define MICROVM_MACHINE_PIC "pic" +#define MICROVM_MACHINE_RTC "rtc" +#define MICROVM_MACHINE_ISA_SERIAL "isa-serial" +#define MICROVM_MACHINE_OPTION_ROMS "x-option-roms" +#define MICROVM_MACHINE_AUTO_KERNEL_CMDLINE "auto-kernel-cmdline" + +typedef struct { +X86MachineClass parent; +HotplugHandler *(*orig_hotplug_handler)(MachineState *machine, +DeviceState *dev); +}MicrovmMachineClass ; + +typedef struct { +X86MachineState parent; + +/* Machine type options */ +OnOffAuto pic; +OnOffAuto pit; +OnOffAuto rtc; +bool isa_serial; +bool option_roms; +bool auto_kernel_cmdline; + +/* Machine state */ +bool kernel_cmdline_fixed; +}MicrovmMachineState ; + +#define TYPE_MICROVM_MACHINE MACHINE_TYPE_NAME("microvm") +#define MICROVM_MACHINE (obj) \ + OBJECT_CHECK(MicrovmMachineState, (obj), TYPE_MICROVM_MACHINE) +#define MICROVM_MACHINE_GET_CLASS (obj) \ + OBJECT_GET_CLASS(MicrovmMachineClass, obj, TYPE_MICROVM_MACHINE) +#define MICROVM_MACHINE_CLASS (class) \ + OBJECT_CLASS_CHECK(MicrovmMachineClass, class, TYPE_MICROVM_MACHINE) + +#endif hw/i386/microvm.c new file +572
-0@@ -0,0 +1,572 @@ +/* +* Copyright (c) 2018 Intel Corporation +* Copyright (c) 2019 Red Hat, Inc. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2 or later, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "qemu/osdep.h" +#include "qemu/error-report.h" +#include "qemu/cutils.h" +#include "qemu/units.h" +#include "qapi/error.h" +#include "qapi/visitor.h" +#include "qapi/qapi-visit-common.h" +#include "sysemu/sysemu.h" +#include "sysemu/cpus.h" +#include "sysemu/numa.h" +#include "sysemu/reset.h" + +#include "hw/loader.h" +#include "hw/irq.h" +#include "hw/kvm/clock.h" +#include "hw/i386/microvm.h" +#include "hw/i386/x86.h" +#include "hw/i386/pc.h" +#include "target/i386/cpu.h" +#include "hw/timer/i8254.h" +#include "hw/timer/mc146818rtc.h" +#include "hw/char/serial.h" +#include "hw/i386/topology.h" +#include "hw/i386/e820_memory_layout.h" +#include "hw/i386/fw_cfg.h" +#include "hw/virtio/virtio-mmio.h" + +#include "cpu.h" +#include "elf.h" +#include "kvm_i386.h" +#include "hw/xen/start_info.h" + +#define MICROVM_BIOS_FILENAME "bios-microvm.bin" + +static void microvm_set_rtc (MicrovmMachineState *mms,ISADevice *s) +{ +X86MachineState *x86ms =X86_MACHINE (mms); +int val; + + val =MIN (x86ms->below_4g_mem_size / KiB,640 ); +rtc_set_memory (s,0x15 , val); +rtc_set_memory (s,0x16 , val >>8 ); +/* extended memory (next 64MiB) */ +if (x86ms->below_4g_mem_size >1 * MiB) { + val = (x86ms->below_4g_mem_size -1 * MiB) / KiB; + }else { + val =0 ; + } +if (val >65535 ) { + val =65535 ; + } +rtc_set_memory (s,0x17 , val); +rtc_set_memory (s,0x18 , val >>8 ); +rtc_set_memory (s,0x30 , val); +rtc_set_memory (s,0x31 , val >>8 ); +/* memory between 16MiB and 4GiB */ +if (x86ms->below_4g_mem_size >16 * MiB) { + val = (x86ms->below_4g_mem_size -16 * MiB) / (64 * KiB); + }else { + val =0 ; + } +if (val >65535 ) { + val =65535 ; + } +rtc_set_memory (s,0x34 , val); +rtc_set_memory (s,0x35 , val >>8 ); +/* memory above 4GiB */ + val = x86ms->above_4g_mem_size /65536 ; +rtc_set_memory (s,0x5b , val); +rtc_set_memory (s,0x5c , val >>8 ); +rtc_set_memory (s,0x5d , val >>16 ); +} + +static void microvm_gsi_handler (void *opaque,int n,int level) +{ +GSIState *s = opaque; + +qemu_set_irq (s->ioapic_irq[n], level); +} + +static void microvm_devices_init (MicrovmMachineState *mms) +{ +X86MachineState *x86ms =X86_MACHINE (mms); +ISABus *isa_bus; +ISADevice *rtc_state; +GSIState *gsi_state; +int i; + +/* Core components */ + + gsi_state =g_malloc0 (sizeof (*gsi_state)); +if (mms->pic ==ON_OFF_AUTO_ON || mms->pic ==ON_OFF_AUTO_AUTO ) { + x86ms->gsi =qemu_allocate_irqs (gsi_handler, gsi_state,GSI_NUM_PINS ); + }else { + x86ms->gsi =qemu_allocate_irqs (microvm_gsi_handler, + gsi_state,GSI_NUM_PINS ); + } + + isa_bus =isa_bus_new (NULL ,get_system_memory (),get_system_io (), + &error_abort); +isa_bus_irqs (isa_bus, x86ms->gsi); + +ioapic_init_gsi (gsi_state,"machine" ); + +kvmclock_create (); + +for (i =0 ; i <VIRTIO_NUM_TRANSPORTS ; i++) { +sysbus_create_simple ("virtio-mmio" , +VIRTIO_MMIO_BASE + i *512 , + x86ms->gsi[VIRTIO_IRQ_BASE + i]); + } + +/* Optional and legacy devices */ + +if (mms->pic ==ON_OFF_AUTO_ON || mms->pic ==ON_OFF_AUTO_AUTO ) { +qemu_irq *i8259; + + i8259 =i8259_init (isa_bus,pc_allocate_cpu_irq ()); +for (i =0 ; i <ISA_NUM_IRQS ; i++) { + gsi_state->i8259_irq[i] = i8259[i]; + } +g_free (i8259); + } + +if (mms->pit ==ON_OFF_AUTO_ON || mms->pit ==ON_OFF_AUTO_AUTO ) { +if (kvm_pit_in_kernel ()) { +kvm_pit_init (isa_bus,0x40 ); + }else { +i8254_pit_init (isa_bus,0x40 ,0 ,NULL ); + } + } + +if (mms->rtc ==ON_OFF_AUTO_ON || + (mms->rtc ==ON_OFF_AUTO_AUTO && !kvm_enabled ())) { + rtc_state =mc146818_rtc_init (isa_bus,2000 ,NULL ); +microvm_set_rtc (mms, rtc_state); + } + +if (mms->isa_serial) { +serial_hds_isa_init (isa_bus,0 ,1 ); + } + +if (bios_name ==NULL ) { + bios_name =MICROVM_BIOS_FILENAME ; + } +x86_bios_rom_init (get_system_memory (), true); +} + +static void microvm_memory_init (MicrovmMachineState *mms) +{ +MachineState *machine =MACHINE (mms); +X86MachineState *x86ms =X86_MACHINE (mms); +MemoryRegion *ram, *ram_below_4g, *ram_above_4g; +MemoryRegion *system_memory =get_system_memory (); +FWCfgState *fw_cfg; +ram_addr_t lowmem; +int i; + +/* +* Check whether RAM fits below 4G (leaving 1/2 GByte for IO memory +* and 256 Mbytes for PCI Express Enhanced Configuration Access Mapping +* also known as MMCFG). +* If it doesn't, we need to split it in chunks below and above 4G. +* In any case, try to make sure that guest addresses aligned at +* 1G boundaries get mapped to host addresses aligned at 1G boundaries. +*/ +if (machine->ram_size >=0xb0000000 ) { + lowmem =0x80000000 ; + }else { + lowmem =0xb0000000 ; + } + +/* +* Handle the machine opt max-ram-below-4g. It is basically doing +* min(qemu limit, user limit). +*/ +if (!x86ms->max_ram_below_4g) { + x86ms->max_ram_below_4g =4 * GiB; + } +if (lowmem > x86ms->max_ram_below_4g) { + lowmem = x86ms->max_ram_below_4g; +if (machine->ram_size - lowmem > lowmem && + lowmem & (1 * GiB -1 )) { +warn_report ("There is possibly poor performance as the ram size " +" (0x%" PRIx64") is more then twice the size of" +" max-ram-below-4g (%" PRIu64") and" +" max-ram-below-4g is not a multiple of 1G." , + (uint64_t )machine->ram_size, x86ms->max_ram_below_4g); + } + } + +if (machine->ram_size > lowmem) { + x86ms->above_4g_mem_size = machine->ram_size - lowmem; + x86ms->below_4g_mem_size = lowmem; + }else { + x86ms->above_4g_mem_size =0 ; + x86ms->below_4g_mem_size = machine->ram_size; + } + + ram =g_malloc (sizeof (*ram)); +memory_region_allocate_system_memory (ram,NULL ,"microvm.ram" , + machine->ram_size); + + ram_below_4g =g_malloc (sizeof (*ram_below_4g)); +memory_region_init_alias (ram_below_4g,NULL ,"ram-below-4g" , ram, +0 , x86ms->below_4g_mem_size); +memory_region_add_subregion (system_memory,0 , ram_below_4g); + +e820_add_entry (0 , x86ms->below_4g_mem_size,E820_RAM ); + +if (x86ms->above_4g_mem_size >0 ) { + ram_above_4g =g_malloc (sizeof (*ram_above_4g)); +memory_region_init_alias (ram_above_4g,NULL ,"ram-above-4g" , ram, + x86ms->below_4g_mem_size, + x86ms->above_4g_mem_size); +memory_region_add_subregion (system_memory,0x100000000ULL , + ram_above_4g); +e820_add_entry (0x100000000ULL , x86ms->above_4g_mem_size,E820_RAM ); + } + + fw_cfg =fw_cfg_init_io_dma (FW_CFG_IO_BASE ,FW_CFG_IO_BASE +4 , + &address_space_memory); + +fw_cfg_add_i16 (fw_cfg,FW_CFG_NB_CPUS , machine->smp.cpus); +fw_cfg_add_i16 (fw_cfg,FW_CFG_MAX_CPUS , machine->smp.max_cpus); +fw_cfg_add_i64 (fw_cfg,FW_CFG_RAM_SIZE , (uint64_t )machine->ram_size); +fw_cfg_add_i32 (fw_cfg,FW_CFG_IRQ0_OVERRIDE ,kvm_allows_irq0_override ()); +fw_cfg_add_bytes (fw_cfg,FW_CFG_E820_TABLE , + &e820_reserve,sizeof (e820_reserve)); +fw_cfg_add_file (fw_cfg,"etc/e820" , e820_table, +sizeof (struct e820_entry ) *e820_get_num_entries ()); + +rom_set_fw (fw_cfg); + +if (machine->kernel_filename !=NULL ) { +x86_load_linux (x86ms, fw_cfg,0 , true, true); + } + +if (mms->option_roms) { +for (i =0 ; i < nb_option_roms; i++) { +rom_add_option (option_rom[i].name, option_rom[i].bootindex); + } + } + + x86ms->fw_cfg = fw_cfg; + x86ms->ioapic_as = &address_space_memory; +} + +static gchar *microvm_get_mmio_cmdline (gchar *name) +{ +gchar *cmdline; +gchar *separator; +long int index; +int ret; + + separator =g_strrstr (name,"." ); +if (!separator) { +return NULL ; + } + +if (qemu_strtol (separator +1 ,NULL ,10 , &index) !=0 ) { +return NULL ; + } + + cmdline =g_malloc0 (VIRTIO_CMDLINE_MAXLEN ); + ret =g_snprintf (cmdline,VIRTIO_CMDLINE_MAXLEN , +" virtio_mmio.device=512@0x%lx:%ld" , +VIRTIO_MMIO_BASE + index *512 , +VIRTIO_IRQ_BASE + index); +if (ret <0 || ret >=VIRTIO_CMDLINE_MAXLEN ) { +g_free (cmdline); +return NULL ; + } + +return cmdline; +} + +static void microvm_fix_kernel_cmdline (MachineState *machine) +{ +X86MachineState *x86ms =X86_MACHINE (machine); +BusState *bus; +BusChild *kid; +char *cmdline; + +/* +* Find MMIO transports with attached devices, and add them to the kernel +* command line. +* +* Yes, this is a hack, but one that heavily improves the UX without +* introducing any significant issues. +*/ + cmdline =g_strdup (machine->kernel_cmdline); + bus =sysbus_get_default (); + QTAILQ_FOREACH(kid, &bus->children, sibling) { +DeviceState *dev = kid->child; +ObjectClass *class =object_get_class (OBJECT (dev)); + +if (class ==object_class_by_name (TYPE_VIRTIO_MMIO )) { +VirtIOMMIOProxy *mmio =VIRTIO_MMIO (OBJECT (dev)); +VirtioBusState *mmio_virtio_bus = &mmio->bus; +BusState *mmio_bus = &mmio_virtio_bus->parent_obj; + +if (!QTAILQ_EMPTY (&mmio_bus->children)) { +gchar *mmio_cmdline =microvm_get_mmio_cmdline (mmio_bus->name); +if (mmio_cmdline) { +char *newcmd =g_strjoin (NULL , cmdline, mmio_cmdline,NULL ); +g_free (mmio_cmdline); +g_free (cmdline); + cmdline = newcmd; + } + } + } + } + +fw_cfg_modify_i32 (x86ms->fw_cfg,FW_CFG_CMDLINE_SIZE ,strlen (cmdline) +1 ); +fw_cfg_modify_string (x86ms->fw_cfg,FW_CFG_CMDLINE_DATA , cmdline); +} + +static void microvm_machine_state_init (MachineState *machine) +{ +MicrovmMachineState *mms =MICROVM_MACHINE (machine); +X86MachineState *x86ms =X86_MACHINE (machine); +Error *local_err =NULL ; + +microvm_memory_init (mms); + +x86_cpus_init (x86ms,CPU_VERSION_LATEST ); +if (local_err) { +error_report_err (local_err); +exit (1 ); + } + +microvm_devices_init (mms); +} + +static void microvm_machine_reset (MachineState *machine) +{ +MicrovmMachineState *mms =MICROVM_MACHINE (machine); +CPUState *cs; +X86CPU *cpu; + +if (machine->kernel_filename !=NULL && + mms->auto_kernel_cmdline && !mms->kernel_cmdline_fixed) { +microvm_fix_kernel_cmdline (machine); + mms->kernel_cmdline_fixed = true; + } + +qemu_devices_reset (); + +CPU_FOREACH (cs) { + cpu =X86_CPU (cs); + +if (cpu->apic_state) { +device_reset (cpu->apic_state); + } + } +} + +static void microvm_machine_get_pic (Object *obj,Visitor *v,const char *name, +void *opaque,Error **errp) +{ +MicrovmMachineState *mms =MICROVM_MACHINE (obj); +OnOffAuto pic = mms->pic; + +visit_type_OnOffAuto (v, name, &pic, errp); +} + +static void microvm_machine_set_pic (Object *obj,Visitor *v,const char *name, +void *opaque,Error **errp) +{ +MicrovmMachineState *mms =MICROVM_MACHINE (obj); + +visit_type_OnOffAuto (v, name, &mms->pic, errp); +} + +static void microvm_machine_get_pit (Object *obj,Visitor *v,const char *name, +void *opaque,Error **errp) +{ +MicrovmMachineState *mms =MICROVM_MACHINE (obj); +OnOffAuto pit = mms->pit; + +visit_type_OnOffAuto (v, name, &pit, errp); +} + +static void microvm_machine_set_pit (Object *obj,Visitor *v,const char *name, +void *opaque,Error **errp) +{ +MicrovmMachineState *mms =MICROVM_MACHINE (obj); + +visit_type_OnOffAuto (v, name, &mms->pit, errp); +} + +static void microvm_machine_get_rtc (Object *obj,Visitor *v,const char *name, +void *opaque,Error **errp) +{ +MicrovmMachineState *mms =MICROVM_MACHINE (obj); +OnOffAuto rtc = mms->rtc; + +visit_type_OnOffAuto (v, name, &rtc, errp); +} + +static void microvm_machine_set_rtc (Object *obj,Visitor *v,const char *name, +void *opaque,Error **errp) +{ +MicrovmMachineState *mms =MICROVM_MACHINE (obj); + +visit_type_OnOffAuto (v, name, &mms->rtc, errp); +} + +static bool microvm_machine_get_isa_serial (Object *obj,Error **errp) +{ +MicrovmMachineState *mms =MICROVM_MACHINE (obj); + +return mms->isa_serial; +} + +static void microvm_machine_set_isa_serial (Object *obj,bool value, +Error **errp) +{ +MicrovmMachineState *mms =MICROVM_MACHINE (obj); + + mms->isa_serial = value; +} + +static bool microvm_machine_get_option_roms (Object *obj,Error **errp) +{ +MicrovmMachineState *mms =MICROVM_MACHINE (obj); + +return mms->option_roms; +} + +static void microvm_machine_set_option_roms (Object *obj,bool value, +Error **errp) +{ +MicrovmMachineState *mms =MICROVM_MACHINE (obj); + + mms->option_roms = value; +} + +static bool microvm_machine_get_auto_kernel_cmdline (Object *obj,Error **errp) +{ +MicrovmMachineState *mms =MICROVM_MACHINE (obj); + +return mms->auto_kernel_cmdline; +} + +static void microvm_machine_set_auto_kernel_cmdline (Object *obj,bool value, +Error **errp) +{ +MicrovmMachineState *mms =MICROVM_MACHINE (obj); + + mms->auto_kernel_cmdline = value; +} + +static void microvm_machine_initfn (Object *obj) +{ +MicrovmMachineState *mms =MICROVM_MACHINE (obj); + +/* Configuration */ + mms->pic =ON_OFF_AUTO_AUTO ; + mms->pit =ON_OFF_AUTO_AUTO ; + mms->rtc =ON_OFF_AUTO_AUTO ; + mms->isa_serial = true; + mms->option_roms = true; + mms->auto_kernel_cmdline = true; + +/* State */ + mms->kernel_cmdline_fixed = false; +} + +static void microvm_class_init (ObjectClass *oc,void *data) +{ +MachineClass *mc =MACHINE_CLASS (oc); + + mc->init = microvm_machine_state_init; + + mc->family ="microvm_i386" ; + mc->desc ="microvm (i386)" ; + mc->units_per_default_bus =1 ; + mc->no_floppy =1 ; + mc->max_cpus =288 ; + mc->has_hotpluggable_cpus = false; + mc->auto_enable_numa_with_memhp = false; + mc->default_cpu_type =TARGET_DEFAULT_CPU_TYPE ; + mc->nvdimm_supported = false; + +/* Avoid relying too much on kernel components */ + mc->default_kernel_irqchip_split = true; + +/* Machine class handlers */ + mc->reset = microvm_machine_reset; + +object_class_property_add (oc,MICROVM_MACHINE_PIC ,"OnOffAuto" , + microvm_machine_get_pic, + microvm_machine_set_pic, +NULL ,NULL , &error_abort); +object_class_property_set_description (oc,MICROVM_MACHINE_PIC , +"Enable i8259 PIC" , &error_abort); + +object_class_property_add (oc,MICROVM_MACHINE_PIT ,"OnOffAuto" , + microvm_machine_get_pit, + microvm_machine_set_pit, +NULL ,NULL , &error_abort); +object_class_property_set_description (oc,MICROVM_MACHINE_PIT , +"Enable i8254 PIT" , &error_abort); + +object_class_property_add (oc,MICROVM_MACHINE_RTC ,"OnOffAuto" , + microvm_machine_get_rtc, + microvm_machine_set_rtc, +NULL ,NULL , &error_abort); +object_class_property_set_description (oc,MICROVM_MACHINE_RTC , +"Enable MC146818 RTC" , &error_abort); + +object_class_property_add_bool (oc,MICROVM_MACHINE_ISA_SERIAL , + microvm_machine_get_isa_serial, + microvm_machine_set_isa_serial, + &error_abort); +object_class_property_set_description (oc,MICROVM_MACHINE_ISA_SERIAL , +"Set off to disable the instantiation an ISA serial port" , + &error_abort); + +object_class_property_add_bool (oc,MICROVM_MACHINE_OPTION_ROMS , + microvm_machine_get_option_roms, + microvm_machine_set_option_roms, + &error_abort); +object_class_property_set_description (oc,MICROVM_MACHINE_OPTION_ROMS , +"Set off to disable loading option ROMs" , &error_abort); + +object_class_property_add_bool (oc,MICROVM_MACHINE_AUTO_KERNEL_CMDLINE , + microvm_machine_get_auto_kernel_cmdline, + microvm_machine_set_auto_kernel_cmdline, + &error_abort); +object_class_property_set_description (oc, +MICROVM_MACHINE_AUTO_KERNEL_CMDLINE , +"Set off to disable adding virtio-mmio devices to the kernel cmdline" , + &error_abort); +} + +static const TypeInfo microvm_machine_info = { + .name =TYPE_MICROVM_MACHINE , + .parent =TYPE_X86_MACHINE , + .instance_size =sizeof (MicrovmMachineState), + .instance_init = microvm_machine_initfn, + .class_size =sizeof (MicrovmMachineClass), + .class_init = microvm_class_init, + .interfaces = (InterfaceInfo []) { + { } + }, +}; + +static void microvm_machine_init (void ) +{ +type_register_static (µvm_machine_info); +} +type_init (microvm_machine_init);hw/i386/Kconfig +10
-0@@ -92,6 +92,16 @@ config Q35 select SMBIOS select FW_CFG_DMA +config MICROVM + bool + imply SERIAL_ISA + select ISA_BUS + select APIC + select IOAPIC + select I8259 + select MC146818RTC + select VIRTIO_MMIO + config VTD boolhw/i386/Makefile.objs +1
-1@@ -4,6 +4,7 @@ obj-y += x86.o obj-y += pc.o obj-$(CONFIG_I440FX) += pc_piix.o obj-$(CONFIG_Q35) += pc_q35.o +obj-$(CONFIG_MICROVM) += microvm.o obj-y += fw_cfg.o pc_sysfw.o obj-y += x86-iommu.o obj-$(CONFIG_VTD) += intel_iommu.o --2.21.0
Signature · 1 line
Marc-André Lureau
Re: [PATCH v10 14/15] hw/i386: Introduce the microvm machine type
Quoted 71 lines · Marc-André Lureau
Hi
Quoted 68 lines · Sergio Lopez
microvm is a machine type inspired by Firecracker and constructed after its machine model.
It's a minimalist machine type without PCI nor ACPI support, designed for short-lived guests. microvm also establishes a baseline for benchmarking and optimizing both QEMU and guest operating systems, since it is optimized for both boot time and footprint.
Signed-off-by Sergio Lopez <[email protected]>Reviewed-by Michael S. Tsirkin <[email protected]>--- default-configs/i386-softmmu.mak | 1 + include/hw/i386/microvm.h | 83 +++++ hw/i386/microvm.c | 572 +++++++++++++++++++++++++++++++ hw/i386/Kconfig | 10 + hw/i386/Makefile.objs | 1 + 5 files changed, 667 insertions(+) create mode 100644 include/hw/i386/microvm.h create mode 100644 hw/i386/microvm.cdefault-configs/i386-softmmu.mak +1
-0@@ -28,3 +28,4 @@ CONFIG_ISAPC=y CONFIG_I440FX=y CONFIG_Q35=y +CONFIG_MICROVM=yinclude/hw/i386/microvm.h new file +32
-0@@ -0,0 +1,83 @@ +/* +* Copyright (c) 2018 Intel Corporation +* Copyright (c) 2019 Red Hat, Inc. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2 or later, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef HW_I386_MICROVM_H +#define HW_I386_MICROVM_H + +#include "qemu-common.h" +#include "exec/hwaddr.h" +#include "qemu/notify.h" + +#include "hw/boards.h" +#include "hw/i386/x86.h" + +/* microvm memory layout */ +#define PVH_START_INFO 0x6000 +#define MEMMAP_START 0x7000 +#define MODLIST_START 0x7800 +#define BOOT_STACK_POINTER 0x8ff0
Quoted 8 lines
include/hw/i386/microvm.h line 38
Quoted 6 lines
include/hw/i386/microvm.h new file +6
-0+#define PML4_START 0x9000 +#define PDPTE_START 0xa000 +#define PDE_START 0xb000 +#define KERNEL_CMDLINE_START 0x20000 +#define EBDA_START 0x9fc00 +#define HIMEM_START 0x100000Those define looks outdated, or am I missing something?
You're right, those are leftovers from pre-v4 patch series. I'll drop them.
Thanks,
Sergio.
Quoted 660 lines
Quoted 660 lines
include/hw/i386/microvm.h new file +45
-0+ +/* Platform virtio definitions */ +#define VIRTIO_MMIO_BASE 0xc0000000 +#define VIRTIO_IRQ_BASE 5 +#define VIRTIO_NUM_TRANSPORTS 8 +#define VIRTIO_CMDLINE_MAXLEN 64 + +/* Machine type options */ +#define MICROVM_MACHINE_PIT "pit" +#define MICROVM_MACHINE_PIC "pic" +#define MICROVM_MACHINE_RTC "rtc" +#define MICROVM_MACHINE_ISA_SERIAL "isa-serial" +#define MICROVM_MACHINE_OPTION_ROMS "x-option-roms" +#define MICROVM_MACHINE_AUTO_KERNEL_CMDLINE "auto-kernel-cmdline" + +typedef struct { +X86MachineClass parent; +HotplugHandler *(*orig_hotplug_handler)(MachineState *machine, +DeviceState *dev); +}MicrovmMachineClass ; + +typedef struct { +X86MachineState parent; + +/* Machine type options */ +OnOffAuto pic; +OnOffAuto pit; +OnOffAuto rtc; +bool isa_serial; +bool option_roms; +bool auto_kernel_cmdline; + +/* Machine state */ +bool kernel_cmdline_fixed; +}MicrovmMachineState ; + +#define TYPE_MICROVM_MACHINE MACHINE_TYPE_NAME("microvm") +#define MICROVM_MACHINE (obj) \ + OBJECT_CHECK(MicrovmMachineState, (obj), TYPE_MICROVM_MACHINE) +#define MICROVM_MACHINE_GET_CLASS (obj) \ + OBJECT_GET_CLASS(MicrovmMachineClass, obj, TYPE_MICROVM_MACHINE) +#define MICROVM_MACHINE_CLASS (class) \ + OBJECT_CLASS_CHECK(MicrovmMachineClass, class, TYPE_MICROVM_MACHINE) + +#endif hw/i386/microvm.c new file +572
-0@@ -0,0 +1,572 @@ +/* +* Copyright (c) 2018 Intel Corporation +* Copyright (c) 2019 Red Hat, Inc. +* +* This program is free software; you can redistribute it and/or modify it +* under the terms and conditions of the GNU General Public License, +* version 2 or later, as published by the Free Software Foundation. +* +* This program is distributed in the hope it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "qemu/osdep.h" +#include "qemu/error-report.h" +#include "qemu/cutils.h" +#include "qemu/units.h" +#include "qapi/error.h" +#include "qapi/visitor.h" +#include "qapi/qapi-visit-common.h" +#include "sysemu/sysemu.h" +#include "sysemu/cpus.h" +#include "sysemu/numa.h" +#include "sysemu/reset.h" + +#include "hw/loader.h" +#include "hw/irq.h" +#include "hw/kvm/clock.h" +#include "hw/i386/microvm.h" +#include "hw/i386/x86.h" +#include "hw/i386/pc.h" +#include "target/i386/cpu.h" +#include "hw/timer/i8254.h" +#include "hw/timer/mc146818rtc.h" +#include "hw/char/serial.h" +#include "hw/i386/topology.h" +#include "hw/i386/e820_memory_layout.h" +#include "hw/i386/fw_cfg.h" +#include "hw/virtio/virtio-mmio.h" + +#include "cpu.h" +#include "elf.h" +#include "kvm_i386.h" +#include "hw/xen/start_info.h" + +#define MICROVM_BIOS_FILENAME "bios-microvm.bin" + +static void microvm_set_rtc (MicrovmMachineState *mms,ISADevice *s) +{ +X86MachineState *x86ms =X86_MACHINE (mms); +int val; + + val =MIN (x86ms->below_4g_mem_size / KiB,640 ); +rtc_set_memory (s,0x15 , val); +rtc_set_memory (s,0x16 , val >>8 ); +/* extended memory (next 64MiB) */ +if (x86ms->below_4g_mem_size >1 * MiB) { + val = (x86ms->below_4g_mem_size -1 * MiB) / KiB; + }else { + val =0 ; + } +if (val >65535 ) { + val =65535 ; + } +rtc_set_memory (s,0x17 , val); +rtc_set_memory (s,0x18 , val >>8 ); +rtc_set_memory (s,0x30 , val); +rtc_set_memory (s,0x31 , val >>8 ); +/* memory between 16MiB and 4GiB */ +if (x86ms->below_4g_mem_size >16 * MiB) { + val = (x86ms->below_4g_mem_size -16 * MiB) / (64 * KiB); + }else { + val =0 ; + } +if (val >65535 ) { + val =65535 ; + } +rtc_set_memory (s,0x34 , val); +rtc_set_memory (s,0x35 , val >>8 ); +/* memory above 4GiB */ + val = x86ms->above_4g_mem_size /65536 ; +rtc_set_memory (s,0x5b , val); +rtc_set_memory (s,0x5c , val >>8 ); +rtc_set_memory (s,0x5d , val >>16 ); +} + +static void microvm_gsi_handler (void *opaque,int n,int level) +{ +GSIState *s = opaque; + +qemu_set_irq (s->ioapic_irq[n], level); +} + +static void microvm_devices_init (MicrovmMachineState *mms) +{ +X86MachineState *x86ms =X86_MACHINE (mms); +ISABus *isa_bus; +ISADevice *rtc_state; +GSIState *gsi_state; +int i; + +/* Core components */ + + gsi_state =g_malloc0 (sizeof (*gsi_state)); +if (mms->pic ==ON_OFF_AUTO_ON || mms->pic ==ON_OFF_AUTO_AUTO ) { + x86ms->gsi =qemu_allocate_irqs (gsi_handler, gsi_state,GSI_NUM_PINS ); + }else { + x86ms->gsi =qemu_allocate_irqs (microvm_gsi_handler, + gsi_state,GSI_NUM_PINS ); + } + + isa_bus =isa_bus_new (NULL ,get_system_memory (),get_system_io (), + &error_abort); +isa_bus_irqs (isa_bus, x86ms->gsi); + +ioapic_init_gsi (gsi_state,"machine" ); + +kvmclock_create (); + +for (i =0 ; i <VIRTIO_NUM_TRANSPORTS ; i++) { +sysbus_create_simple ("virtio-mmio" , +VIRTIO_MMIO_BASE + i *512 , + x86ms->gsi[VIRTIO_IRQ_BASE + i]); + } + +/* Optional and legacy devices */ + +if (mms->pic ==ON_OFF_AUTO_ON || mms->pic ==ON_OFF_AUTO_AUTO ) { +qemu_irq *i8259; + + i8259 =i8259_init (isa_bus,pc_allocate_cpu_irq ()); +for (i =0 ; i <ISA_NUM_IRQS ; i++) { + gsi_state->i8259_irq[i] = i8259[i]; + } +g_free (i8259); + } + +if (mms->pit ==ON_OFF_AUTO_ON || mms->pit ==ON_OFF_AUTO_AUTO ) { +if (kvm_pit_in_kernel ()) { +kvm_pit_init (isa_bus,0x40 ); + }else { +i8254_pit_init (isa_bus,0x40 ,0 ,NULL ); + } + } + +if (mms->rtc ==ON_OFF_AUTO_ON || + (mms->rtc ==ON_OFF_AUTO_AUTO && !kvm_enabled ())) { + rtc_state =mc146818_rtc_init (isa_bus,2000 ,NULL ); +microvm_set_rtc (mms, rtc_state); + } + +if (mms->isa_serial) { +serial_hds_isa_init (isa_bus,0 ,1 ); + } + +if (bios_name ==NULL ) { + bios_name =MICROVM_BIOS_FILENAME ; + } +x86_bios_rom_init (get_system_memory (), true); +} + +static void microvm_memory_init (MicrovmMachineState *mms) +{ +MachineState *machine =MACHINE (mms); +X86MachineState *x86ms =X86_MACHINE (mms); +MemoryRegion *ram, *ram_below_4g, *ram_above_4g; +MemoryRegion *system_memory =get_system_memory (); +FWCfgState *fw_cfg; +ram_addr_t lowmem; +int i; + +/* +* Check whether RAM fits below 4G (leaving 1/2 GByte for IO memory +* and 256 Mbytes for PCI Express Enhanced Configuration Access Mapping +* also known as MMCFG). +* If it doesn't, we need to split it in chunks below and above 4G. +* In any case, try to make sure that guest addresses aligned at +* 1G boundaries get mapped to host addresses aligned at 1G boundaries. +*/ +if (machine->ram_size >=0xb0000000 ) { + lowmem =0x80000000 ; + }else { + lowmem =0xb0000000 ; + } + +/* +* Handle the machine opt max-ram-below-4g. It is basically doing +* min(qemu limit, user limit). +*/ +if (!x86ms->max_ram_below_4g) { + x86ms->max_ram_below_4g =4 * GiB; + } +if (lowmem > x86ms->max_ram_below_4g) { + lowmem = x86ms->max_ram_below_4g; +if (machine->ram_size - lowmem > lowmem && + lowmem & (1 * GiB -1 )) { +warn_report ("There is possibly poor performance as the ram size " +" (0x%" PRIx64") is more then twice the size of" +" max-ram-below-4g (%" PRIu64") and" +" max-ram-below-4g is not a multiple of 1G." , + (uint64_t )machine->ram_size, x86ms->max_ram_below_4g); + } + } + +if (machine->ram_size > lowmem) { + x86ms->above_4g_mem_size = machine->ram_size - lowmem; + x86ms->below_4g_mem_size = lowmem; + }else { + x86ms->above_4g_mem_size =0 ; + x86ms->below_4g_mem_size = machine->ram_size; + } + + ram =g_malloc (sizeof (*ram)); +memory_region_allocate_system_memory (ram,NULL ,"microvm.ram" , + machine->ram_size); + + ram_below_4g =g_malloc (sizeof (*ram_below_4g)); +memory_region_init_alias (ram_below_4g,NULL ,"ram-below-4g" , ram, +0 , x86ms->below_4g_mem_size); +memory_region_add_subregion (system_memory,0 , ram_below_4g); + +e820_add_entry (0 , x86ms->below_4g_mem_size,E820_RAM ); + +if (x86ms->above_4g_mem_size >0 ) { + ram_above_4g =g_malloc (sizeof (*ram_above_4g)); +memory_region_init_alias (ram_above_4g,NULL ,"ram-above-4g" , ram, + x86ms->below_4g_mem_size, + x86ms->above_4g_mem_size); +memory_region_add_subregion (system_memory,0x100000000ULL , + ram_above_4g); +e820_add_entry (0x100000000ULL , x86ms->above_4g_mem_size,E820_RAM ); + } + + fw_cfg =fw_cfg_init_io_dma (FW_CFG_IO_BASE ,FW_CFG_IO_BASE +4 , + &address_space_memory); + +fw_cfg_add_i16 (fw_cfg,FW_CFG_NB_CPUS , machine->smp.cpus); +fw_cfg_add_i16 (fw_cfg,FW_CFG_MAX_CPUS , machine->smp.max_cpus); +fw_cfg_add_i64 (fw_cfg,FW_CFG_RAM_SIZE , (uint64_t )machine->ram_size); +fw_cfg_add_i32 (fw_cfg,FW_CFG_IRQ0_OVERRIDE ,kvm_allows_irq0_override ()); +fw_cfg_add_bytes (fw_cfg,FW_CFG_E820_TABLE , + &e820_reserve,sizeof (e820_reserve)); +fw_cfg_add_file (fw_cfg,"etc/e820" , e820_table, +sizeof (struct e820_entry ) *e820_get_num_entries ()); + +rom_set_fw (fw_cfg); + +if (machine->kernel_filename !=NULL ) { +x86_load_linux (x86ms, fw_cfg,0 , true, true); + } + +if (mms->option_roms) { +for (i =0 ; i < nb_option_roms; i++) { +rom_add_option (option_rom[i].name, option_rom[i].bootindex); + } + } + + x86ms->fw_cfg = fw_cfg; + x86ms->ioapic_as = &address_space_memory; +} + +static gchar *microvm_get_mmio_cmdline (gchar *name) +{ +gchar *cmdline; +gchar *separator; +long int index; +int ret; + + separator =g_strrstr (name,"." ); +if (!separator) { +return NULL ; + } + +if (qemu_strtol (separator +1 ,NULL ,10 , &index) !=0 ) { +return NULL ; + } + + cmdline =g_malloc0 (VIRTIO_CMDLINE_MAXLEN ); + ret =g_snprintf (cmdline,VIRTIO_CMDLINE_MAXLEN , +" virtio_mmio.device=512@0x%lx:%ld" , +VIRTIO_MMIO_BASE + index *512 , +VIRTIO_IRQ_BASE + index); +if (ret <0 || ret >=VIRTIO_CMDLINE_MAXLEN ) { +g_free (cmdline); +return NULL ; + } + +return cmdline; +} + +static void microvm_fix_kernel_cmdline (MachineState *machine) +{ +X86MachineState *x86ms =X86_MACHINE (machine); +BusState *bus; +BusChild *kid; +char *cmdline; + +/* +* Find MMIO transports with attached devices, and add them to the kernel +* command line. +* +* Yes, this is a hack, but one that heavily improves the UX without +* introducing any significant issues. +*/ + cmdline =g_strdup (machine->kernel_cmdline); + bus =sysbus_get_default (); + QTAILQ_FOREACH(kid, &bus->children, sibling) { +DeviceState *dev = kid->child; +ObjectClass *class =object_get_class (OBJECT (dev)); + +if (class ==object_class_by_name (TYPE_VIRTIO_MMIO )) { +VirtIOMMIOProxy *mmio =VIRTIO_MMIO (OBJECT (dev)); +VirtioBusState *mmio_virtio_bus = &mmio->bus; +BusState *mmio_bus = &mmio_virtio_bus->parent_obj; + +if (!QTAILQ_EMPTY (&mmio_bus->children)) { +gchar *mmio_cmdline =microvm_get_mmio_cmdline (mmio_bus->name); +if (mmio_cmdline) { +char *newcmd =g_strjoin (NULL , cmdline, mmio_cmdline,NULL ); +g_free (mmio_cmdline); +g_free (cmdline); + cmdline = newcmd; + } + } + } + } + +fw_cfg_modify_i32 (x86ms->fw_cfg,FW_CFG_CMDLINE_SIZE ,strlen (cmdline) +1 ); +fw_cfg_modify_string (x86ms->fw_cfg,FW_CFG_CMDLINE_DATA , cmdline); +} + +static void microvm_machine_state_init (MachineState *machine) +{ +MicrovmMachineState *mms =MICROVM_MACHINE (machine); +X86MachineState *x86ms =X86_MACHINE (machine); +Error *local_err =NULL ; + +microvm_memory_init (mms); + +x86_cpus_init (x86ms,CPU_VERSION_LATEST ); +if (local_err) { +error_report_err (local_err); +exit (1 ); + } + +microvm_devices_init (mms); +} + +static void microvm_machine_reset (MachineState *machine) +{ +MicrovmMachineState *mms =MICROVM_MACHINE (machine); +CPUState *cs; +X86CPU *cpu; + +if (machine->kernel_filename !=NULL && + mms->auto_kernel_cmdline && !mms->kernel_cmdline_fixed) { +microvm_fix_kernel_cmdline (machine); + mms->kernel_cmdline_fixed = true; + } + +qemu_devices_reset (); + +CPU_FOREACH (cs) { + cpu =X86_CPU (cs); + +if (cpu->apic_state) { +device_reset (cpu->apic_state); + } + } +} + +static void microvm_machine_get_pic (Object *obj,Visitor *v,const char *name, +void *opaque,Error **errp) +{ +MicrovmMachineState *mms =MICROVM_MACHINE (obj); +OnOffAuto pic = mms->pic; + +visit_type_OnOffAuto (v, name, &pic, errp); +} + +static void microvm_machine_set_pic (Object *obj,Visitor *v,const char *name, +void *opaque,Error **errp) +{ +MicrovmMachineState *mms =MICROVM_MACHINE (obj); + +visit_type_OnOffAuto (v, name, &mms->pic, errp); +} + +static void microvm_machine_get_pit (Object *obj,Visitor *v,const char *name, +void *opaque,Error **errp) +{ +MicrovmMachineState *mms =MICROVM_MACHINE (obj); +OnOffAuto pit = mms->pit; + +visit_type_OnOffAuto (v, name, &pit, errp); +} + +static void microvm_machine_set_pit (Object *obj,Visitor *v,const char *name, +void *opaque,Error **errp) +{ +MicrovmMachineState *mms =MICROVM_MACHINE (obj); + +visit_type_OnOffAuto (v, name, &mms->pit, errp); +} + +static void microvm_machine_get_rtc (Object *obj,Visitor *v,const char *name, +void *opaque,Error **errp) +{ +MicrovmMachineState *mms =MICROVM_MACHINE (obj); +OnOffAuto rtc = mms->rtc; + +visit_type_OnOffAuto (v, name, &rtc, errp); +} + +static void microvm_machine_set_rtc (Object *obj,Visitor *v,const char *name, +void *opaque,Error **errp) +{ +MicrovmMachineState *mms =MICROVM_MACHINE (obj); + +visit_type_OnOffAuto (v, name, &mms->rtc, errp); +} + +static bool microvm_machine_get_isa_serial (Object *obj,Error **errp) +{ +MicrovmMachineState *mms =MICROVM_MACHINE (obj); + +return mms->isa_serial; +} + +static void microvm_machine_set_isa_serial (Object *obj,bool value, +Error **errp) +{ +MicrovmMachineState *mms =MICROVM_MACHINE (obj); + + mms->isa_serial = value; +} + +static bool microvm_machine_get_option_roms (Object *obj,Error **errp) +{ +MicrovmMachineState *mms =MICROVM_MACHINE (obj); + +return mms->option_roms; +} + +static void microvm_machine_set_option_roms (Object *obj,bool value, +Error **errp) +{ +MicrovmMachineState *mms =MICROVM_MACHINE (obj); + + mms->option_roms = value; +} + +static bool microvm_machine_get_auto_kernel_cmdline (Object *obj,Error **errp) +{ +MicrovmMachineState *mms =MICROVM_MACHINE (obj); + +return mms->auto_kernel_cmdline; +} + +static void microvm_machine_set_auto_kernel_cmdline (Object *obj,bool value, +Error **errp) +{ +MicrovmMachineState *mms =MICROVM_MACHINE (obj); + + mms->auto_kernel_cmdline = value; +} + +static void microvm_machine_initfn (Object *obj) +{ +MicrovmMachineState *mms =MICROVM_MACHINE (obj); + +/* Configuration */ + mms->pic =ON_OFF_AUTO_AUTO ; + mms->pit =ON_OFF_AUTO_AUTO ; + mms->rtc =ON_OFF_AUTO_AUTO ; + mms->isa_serial = true; + mms->option_roms = true; + mms->auto_kernel_cmdline = true; + +/* State */ + mms->kernel_cmdline_fixed = false; +} + +static void microvm_class_init (ObjectClass *oc,void *data) +{ +MachineClass *mc =MACHINE_CLASS (oc); + + mc->init = microvm_machine_state_init; + + mc->family ="microvm_i386" ; + mc->desc ="microvm (i386)" ; + mc->units_per_default_bus =1 ; + mc->no_floppy =1 ; + mc->max_cpus =288 ; + mc->has_hotpluggable_cpus = false; + mc->auto_enable_numa_with_memhp = false; + mc->default_cpu_type =TARGET_DEFAULT_CPU_TYPE ; + mc->nvdimm_supported = false; + +/* Avoid relying too much on kernel components */ + mc->default_kernel_irqchip_split = true; + +/* Machine class handlers */ + mc->reset = microvm_machine_reset; + +object_class_property_add (oc,MICROVM_MACHINE_PIC ,"OnOffAuto" , + microvm_machine_get_pic, + microvm_machine_set_pic, +NULL ,NULL , &error_abort); +object_class_property_set_description (oc,MICROVM_MACHINE_PIC , +"Enable i8259 PIC" , &error_abort); + +object_class_property_add (oc,MICROVM_MACHINE_PIT ,"OnOffAuto" , + microvm_machine_get_pit, + microvm_machine_set_pit, +NULL ,NULL , &error_abort); +object_class_property_set_description (oc,MICROVM_MACHINE_PIT , +"Enable i8254 PIT" , &error_abort); + +object_class_property_add (oc,MICROVM_MACHINE_RTC ,"OnOffAuto" , + microvm_machine_get_rtc, + microvm_machine_set_rtc, +NULL ,NULL , &error_abort); +object_class_property_set_description (oc,MICROVM_MACHINE_RTC , +"Enable MC146818 RTC" , &error_abort); + +object_class_property_add_bool (oc,MICROVM_MACHINE_ISA_SERIAL , + microvm_machine_get_isa_serial, + microvm_machine_set_isa_serial, + &error_abort); +object_class_property_set_description (oc,MICROVM_MACHINE_ISA_SERIAL , +"Set off to disable the instantiation an ISA serial port" , + &error_abort); + +object_class_property_add_bool (oc,MICROVM_MACHINE_OPTION_ROMS , + microvm_machine_get_option_roms, + microvm_machine_set_option_roms, + &error_abort); +object_class_property_set_description (oc,MICROVM_MACHINE_OPTION_ROMS , +"Set off to disable loading option ROMs" , &error_abort); + +object_class_property_add_bool (oc,MICROVM_MACHINE_AUTO_KERNEL_CMDLINE , + microvm_machine_get_auto_kernel_cmdline, + microvm_machine_set_auto_kernel_cmdline, + &error_abort); +object_class_property_set_description (oc, +MICROVM_MACHINE_AUTO_KERNEL_CMDLINE , +"Set off to disable adding virtio-mmio devices to the kernel cmdline" , + &error_abort); +} + +static const TypeInfo microvm_machine_info = { + .name =TYPE_MICROVM_MACHINE , + .parent =TYPE_X86_MACHINE , + .instance_size =sizeof (MicrovmMachineState), + .instance_init = microvm_machine_initfn, + .class_size =sizeof (MicrovmMachineClass), + .class_init = microvm_class_init, + .interfaces = (InterfaceInfo []) { + { } + }, +}; + +static void microvm_machine_init (void ) +{ +type_register_static (µvm_machine_info); +} +type_init (microvm_machine_init);hw/i386/Kconfig +10
-0@@ -92,6 +92,16 @@ config Q35 select SMBIOS select FW_CFG_DMA +config MICROVM + bool + imply SERIAL_ISA + select ISA_BUS + select APIC + select IOAPIC + select I8259 + select MC146818RTC + select VIRTIO_MMIO + config VTD boolhw/i386/Makefile.objs +1
-1@@ -4,6 +4,7 @@ obj-y += x86.o obj-y += pc.o obj-$(CONFIG_I440FX) += pc_piix.o obj-$(CONFIG_Q35) += pc_q35.o +obj-$(CONFIG_MICROVM) += microvm.o obj-y += fw_cfg.o pc_sysfw.o obj-y += x86-iommu.o obj-$(CONFIG_VTD) += intel_iommu.o --2.21.0
PATCH v10 15/15 MAINTAINERS: add microvm related files
In reply to Sergio LopezAdd a new "microvm" section under "X86 Machines" with the new files related to this machine type.
--- MAINTAINERS | 9 +++++++++ 1 file changed, 9 insertions(+)
MAINTAINERS +9 -0
@@ -1275,6 +1275,15 @@ F: include/hw/timer/hpet.h F: include/hw/timer/i8254* F: include/hw/timer/mc146818rtc* +microvm +M: Sergio Lopez <[email protected]> +M: Paolo Bonzini <[email protected]> +S: Maintained +F: docs/microvm.rst +F: hw/i386/microvm.c +F: include/hw/i386/microvm.h +F: pc-bios/bios-microvm.bin + Machine core M: Eduardo Habkost <[email protected]> M: Marcel Apfelbaum <[email protected]>
Signature · 1 line
2.21.0