初始化一个board
qmp_x_exit_preconfig
-》qemu_init_board();
-》numa_uses_legacy_mem() && !current_machine->ram_memdev_id) {
-》create_default_memdev(current_machine, mem_path)
-》qemu_plugin_load_list(&plugin_list, &error_fatal)
-》machine_run_board_init(current_machine)
-》accel_init_interfaces(ACCEL_GET_CLASS(machine->accelerator))
-》accel_init_ops_interfaces(ac);
-》ops->ops_init(ops)
-》tcg_accel_ops_init
-》ops->create_vcpu_thread = mttcg_start_vcpu_thread;
-》accel_init_cpu_interfaces(ac);
-》machine_class->init(machine) // vexpress_common_init,初始化一个具体的 machine,比如“arm vexpress 开发板”
-》vexpress_common_init
-》drive_check_orphaned();
-》realtime_init();
-》qemu_create_cli_devices();
-》qemu_machine_creation_done();
机器1:Virt arm64 machine
virt machine定义:
static const TypeInfo virt_machine_info = {
.name = TYPE_VIRT_MACHINE,
.parent = TYPE_MACHINE,
.abstract = true,
.instance_size = sizeof(VirtMachineState),
.class_size = sizeof(VirtMachineClass),
.class_init = virt_machine_class_init,
.instance_init = virt_instance_init,
.interfaces = (InterfaceInfo[]) {
{ TYPE_HOTPLUG_HANDLER },
{ }
},
};
machvirt_init:
machvirt_init
-》for (n = 0; n < possible_cpus->len; n++) { //有几个核,就循环几次
-》cpuobj = object_new(possible_cpus->cpus[n].type)
TypeImpl *ti = type_get_by_name(typename);
object_new_with_type(ti)
type_initialize(type)
-》qdev_realize(DEVICE(cpuobj), NULL, &error_fatal) //调用aarch64 cpu的 realize 函数
-》 aarch64 &= object_property_get_bool(cpuobj, "aarch64", NULL);
-》create_rtc(vms);
-》create_pcie(vms) //创建PCIE设备
-》arm_load_kernel(ARM_CPU(first_cpu), machine, &vms->bootinfo) //加载内核 hw/arm/boot.c
virt arm64 地址映射
virt支持的CPU型号:
static const char *valid_cpus[] = {
ARM_CPU_TYPE_NAME("cortex-a7"),
ARM_CPU_TYPE_NAME("cortex-a15"),
ARM_CPU_TYPE_NAME("cortex-a53"),
ARM_CPU_TYPE_NAME("cortex-a57"),
ARM_CPU_TYPE_NAME("cortex-a72"),
ARM_CPU_TYPE_NAME("a64fx"),
ARM_CPU_TYPE_NAME("host"),
ARM_CPU_TYPE_NAME("max"),
};
机器2:vexpress machine
由于下面这里定义了 vexpress_machine_init:
type_init(vexpress_machine_init)
而 type_init() 宏又指向了 module_init,module_init 宏会将这个type通过register_module_ini()插入到&init_type_list[type]全局链表中,
所以在qemu_init中,会调用qemu_init_subsystems(),在qemu_init_subsystems()中,会调用module_call_init(MODULE_INIT_QOM),从而调用到vexpress_machine_init()
#define type_init(function) module_init(function, MODULE_INIT_QOM)
vexpress_machine_init
vexpress_machine_init
-》type_register_static(&vexpress_info)
-》type_register_static(&vexpress_a9_info)
-》type_register_static(&vexpress_a15_info)
-》type_register(info)
-》type_table_add(ti)
-》g_hash_table_insert(type_table_get(), (void *)ti->name, ti) //插入到一个hash表中去
vexpress_a15_info定义:
如下,代表一个虚拟的arm vexpress_a15的开发板:
static const TypeInfo vexpress_a15_info = {
.name = TYPE_VEXPRESS_A15_MACHINE,
.parent = TYPE_VEXPRESS_MACHINE, //它的父亲是 TYPE_VEXPRESS_MACHINE
.class_init = vexpress_a15_class_init,
.instance_init = vexpress_a15_instance_init,
};
Parent 机器的TYPE_VEXPRESS_MACHINE 定义如下:
static const TypeInfo vexpress_info = {
.name = TYPE_VEXPRESS_MACHINE,
.parent = TYPE_MACHINE,
.abstract = true,
.instance_size = sizeof(VexpressMachineState),
.instance_init = vexpress_instance_init,
.class_size = sizeof(VexpressMachineClass),
.class_init = vexpress_class_init, //这里的 class_init具体在哪里调用,还需要进一步理解?
};
vexpress_info的parent,又是machine_info:
static const TypeInfo machine_info = {
.name = TYPE_MACHINE,
.parent = TYPE_OBJECT,
.abstract = true,
.class_size = sizeof(MachineClass),
.class_init = machine_class_init,
.class_base_init = machine_class_base_init,
.instance_size = sizeof(MachineState),
.instance_init = machine_initfn,
.instance_finalize = machine_finalize,
};
vexpress machine 初始化
machine_class_init
-》mc->default_ram_size = 128 * MiB //默认的内存设置为 128MB
-》object_class_property_add_str(oc, "kernel", machine_get_kernel, machine_set_kernel); //解析 -kernel 参数
-》object_class_property_set_description(oc, "kernel","Linux kernel image file");
-》object_class_property_add(oc, "smp", "SMPConfiguration",machine_get_smp, machine_set_smp, NULL, NULL); //解析 -smp 参数
-》 object_class_property_set_description(oc, "smp","CPU topology");
vexpress_class_init
-》mc->desc = "ARM Versatile Express";
-》mc->init = vexpress_common_init; //前面的 machine_class->init(machine) ,最终实际上调用到了 vexpress_common_init()
-》mc->max_cpus = 4;
-》mc->ignore_memory_transaction_failures = true;
-》mc->default_ram_id = "vexpress.highmem";
因此,前面的 machine_class->init(machine) ,最终实际上调用到了 vexpress_common_init()
vexpress_common_init
-》MemoryRegion *sysmem = get_system_memory();
-》MemoryRegion *vram = g_new(MemoryRegion, 1);
-》MemoryRegion *sram = g_new(MemoryRegion, 1);
-》MemoryRegion *flashalias = g_new(MemoryRegion, 1);
-》MemoryRegion *flash0mem;
-》daughterboard->init(vms, machine->ram_size, machine->cpu_type, pic);
-》arm_load_kernel(ARM_CPU(first_cpu), machine, &daughterboard->bootinfo)
-》arm_setup_direct_kernel_boot(cpu, info) //加载kernel image 文件
-》load_uimage_as(info->kernel_filename, &entry, &loadaddr, //从info->kernel_filename 文件中加载kernel image
&is_linux, NULL, NULL, as)
-》load_ramdisk_as(info->initrd_filename, //从info->initrd_filename中加载 ramdisk文件
info->initrd_start,
ram_end - info->initrd_start, as)
-》arm_load_dtb(info->dtb_start, info, info->dtb_limit, as, ms) //从加载DTB 文件
load_device_tree(filename, &size)
load_image_size(filename_path, fdt, dt_size)
read(fd, addr + l, size - l) //读文件