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
-devicein 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.cx86 q35:
pc_q35_init()athw/i386/pc_q35.carm virt:
machvirt_init()athw/arm/virt.carm vexpress-a15:
vexpress_common_init()=>a15_daughterboard_init()athw/arm/vexpress.cfind 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.cne2k:
pci_ne2000_realize()athw/net/ne2000.crtl8139:
pci_rtl8139_realize()athw/net/rtl8139.cvirtio:
virtio_net_device_realize()athw/net/virtio-net.cfind 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
TypeInfostruct, 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 ofrealizedproperty.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