QEMU system init¶
Basic¶
entry point:
vl.c::main()
machine initialization
CLI option
-M <machine>
decides it.init function:
machine_class->init(machine_class)
initialize motherboard or development board.
initialize cpu, memory, bus, devices for motherboard
misc device init:
device_init_func()
CLI option
-device <device>,<options>
.for each
-device
in CLI options, calldevice_init_func()
to initialize it.device_init_func()
callsdev->realize()
to init device.e.g. ivshmem(Inter-VM Share Memory) is initialized by
ivshmem_realize()
.
QEMU IO thread runs into main loop:
main_loop()
multi-threading
CPU initialization will create (
pthread_create()
) multiple threads, which is called QEMU vCPU thread. The thread number is equals to vCPU number.More: QEMU thread and event model , QEMU/KVM architecture overview
Machine Init¶
all machines are initialized by class init()
member function.
main()
runs it:
// vl.c::main()
current_machine = MACHINE(object_new(object_class_get_name(OBJECT_CLASS(machine_class))));
machine_class->init(current_machine)
options¶
machine_class->init()
depends on CLI option: -M <machine>
, and default machine of qemu-system-x86_64
is i440FX.
machine_class->init()
common options
x86 i440FX:
pc_init1()
athw/i386/pc_piix.c
x86 q35:
pc_q35_init()
athw/i386/pc_q35.c
arm virt:
machvirt_init()
athw/arm/virt.c
arm vexpress-a15:
vexpress_common_init()
=>a15_daughterboard_init()
athw/arm/vexpress.c
find more options by QEMU help:
$ qemu-system-arm -M help virt QEMU 2.8 ARM Virtual Machine (alias of virt-2.8) vexpress-a15 ARM Versatile Express for Cortex-A15 ... # x86 -M help shows pc and q35
internal¶
Using i440FX as example. i440FX’s init() is pc_init1()
.
pc_init1()
initialize init cpu, memory, bus, devices for motherboard i440FX.
CPU:
pc_cpus_init()
. it usepthread_create()
to create vCPU threads in KVM Mode, and vCPU threads useioctl(KVM_CREATE_VCPU)
to runs guest OS.Memory:
pc_memory_init()
. it initialize global variablesystem_memory
.VGA:
pc_vga_init()
, it calls realize function of VGA device (e.g.pci_cirrus_vga_realize()
)NIC:
pc_nic_init()
, it calls realize function of NIC device (e.g.pci_e1000_realize()
)IDE:
pci_piix3_ide_init()
, init disk …
Device Init¶
all QEMU devices is initialized by realize()
member function, which is triggered by setter of realized
property.
example source code (i440FX init function initialize NIC):
// pc_init1() => pc_nic_init() => pci_e1000_realize() pc_nic_init() => pci_nic_init_nofail() => qdev_init_nofail() => object_property_set_bool(OBJECT(dev), true, "realized", &err); // set ``realized`` property to true. => pci_e1000_realize(); // e1000 NIC's realize function.
options¶
NIC common options
e1000:
pci_e1000_realize()
athw/net/e1000.c
ne2k:
pci_ne2000_realize()
athw/net/ne2000.c
rtl8139:
pci_rtl8139_realize()
athw/net/rtl8139.c
virtio:
virtio_net_device_realize()
athw/net/virtio-net.c
find more options
QEMU help:
$ qemu-system-x86_64 -device help Network devices: name "e1000", bus PCI, alias "e1000-82540em", desc "Intel Gigabit Ethernet" name "e1000-82544gc", bus PCI, desc "Intel Gigabit Ethernet" name "ne2k_isa", bus ISA name "ne2k_pci", bus PCI name "pcnet", bus PCI name "rtl8139", bus PCI ...
searching source code:
$ grep -Rn hw/net/ -e "realize" hw/net/e1000.c:1587:static void pci_e1000_realize(PCIDevice *pci_dev, Error **errp) hw/net/ne2000.c:720:static void pci_ne2000_realize(PCIDevice *pci_dev, Error **errp) hw/net/ne2000-isa.c:62:static void isa_ne2000_realizefn(DeviceState *dev, Error **errp) hw/net/pcnet-pci.c:281:static void pci_pcnet_realize(PCIDevice *pci_dev, Error **errp) ...
Code detail and Note¶
QEMU implements OOP in C, QEMU name it’s OO model QOM(QEMU Object Model).
each classes has a
TypeInfo
struct, which define some metadata like class name and parent classes.more about QOM: QEMU Object Model
QEMU devices are implemented by QDev. QDev is reimplemented on the QOM currently.
QDev is a class, and it is a base class of all QEMU devices.
motherboard, cpu, vga, nic inherit QDev.
all QDev device is initialized by
realize()
member function. It is triggered by setter ofrealized
property.object_property_set_bool(OBJECT(dev), true, "realized", &err);
why
machine_class->init()
callspc_init1()
:// in QEMU v2.7 // expand MACRO DEFINE_I440FX_MACHINE, which define motherboard class "pc-i440fx-2.7" (QEMU class by QEMU Object Model) DEFINE_I440FX_MACHINE(v2_7, "pc-i440fx-2.7", NULL, pc_i440fx_2_7_machine_options); // DEFINE_PC_MACHINE(v2_7, "pc-i440fx-2.7", pc_init_v2_7, pc_i440fx_2_7_machine_options); type_init(pc_machine_init_v2_7) static void pc_machine_init_v2_7(void) { type_register(&pc_machine_type_v2_7); } static const TypeInfo pc_machine_type_v2_7 = { .name = "pc-i440fx-2.7", .parent = "generic-pc-machine", .class_init = pc_machine_v2_7_class_init, } pc_machine_v2_7_class_init(ObjectClass *oc, void *data){ MachineClass *mc = MACHINE_CLASS(oc); pc_i440fx_2_7_machine_options(mc); mc->name = "pc-i440fx-2.7" mc->init = pc_init_v2_7; // mc->init() is pc_init_v2_7(), which calls pc_init1() } pc_init_v2_7(MachineState *machine){ ... // call compat pc_init1() }
QEMU has GLib dependecies. it uses GLib data type, data structures, and event loop.
reference¶
QEMU wiki - Documentation/Platforms/PC, QEMU wiki - Documentation/Platforms/ARM
qemu-system-x86_64 -M help
,qemu-system-arm -M help