QEMU 6.2 源代码分析之 [ 2 ] —— 开发板虚拟化

初始化一个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)  //读文件
  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值