qemu启动过程笔记
//定义结构
static struct QemuSpiceOps real_spice_ops = {
.init = qemu_spice_init,
.display_init = qemu_spice_display_init,
.migrate_info = qemu_spice_migrate_info,
.set_passwd = qemu_spice_set_passwd,
.set_pw_expire = qemu_spice_set_pw_expire,
.display_add_client = qemu_spice_display_add_client,
.add_interface = qemu_spice_add_interface,
.qmp_query = qmp_query_spice_real,
};
//添加参数
static void spice_register_config(void)
{
qemu_spice = real_spice_ops;
qemu_add_opts(&qemu_spice_opts);
}
//注册spice_register_config
opts_init(spice_register_config);
//宏替换
#define block_init(function) module_init(function, MODULE_INIT_BLOCK)
#define opts_init(function) module_init(function, MODULE_INIT_OPTS)
#define type_init(function) module_init(function, MODULE_INIT_QOM)
#define trace_init(function) module_init(function, MODULE_INIT_TRACE)
#define xen_backend_init(function) module_init(function, MODULE_INIT_XEN_BACKEND)
#define libqos_init(function) module_init(function, MODULE_INIT_LIBQOS)
#define fuzz_target_init(function) module_init(function, MODULE_INIT_FUZZ_TARGET)
#define migration_init(function) module_init(function, MODULE_INIT_MIGRATION)
//定义调用函数
#define module_init(function, type) \
static void __attribute__((constructor)) do_qemu_init_ ## function(void) \
{ \
register_dso_module_init(function, type); \
}
#else
/* This should not be used directly. Use block_init etc. instead. */
#define module_init(function, type) \
static void __attribute__((constructor)) do_qemu_init_ ## function(void) \
{ \
register_module_init(function, type); \
}
#endif
//将函数和类型插入到相应类型的列表中
void register_module_init(void (*fn)(void), module_init_type type)
{
ModuleEntry *e;
ModuleTypeList *l;
e = g_malloc0(sizeof(*e));
e->init = fn;
e->type = type;
l = find_type(type);
QTAILQ_INSERT_TAIL(l, e, node);
}
//保存的列表
static ModuleTypeList init_type_list[MODULE_INIT_MAX];
static bool modules_init_done[MODULE_INIT_MAX];
2、main函数,定义在softmmu/main.c, main() -> qemu_main() -> qemu_init() ->qemu_init_subsystems() -> module_call_init(MODULE_INIT_QOM)。
int qemu_default_main(void)
{
int status;
status = qemu_main_loop();
qemu_cleanup();
return status;
}
int (*qemu_main)(void) = qemu_default_main;
int main(int argc, char **argv)
{
qemu_init(argc, argv);
return qemu_main();
}
void qemu_init(int argc, char **argv)
{
QemuOpts *opts;
QemuOpts *icount_opts = NULL, *accel_opts = NULL;
QemuOptsList *olist;
int optind;
const char *optarg;
MachineClass *machine_class;
bool userconfig = true;
FILE *vmstate_dump_file = NULL;
//添加参数列表
qemu_add_opts(&qemu_drive_opts);
qemu_add_drive_opts(&qemu_legacy_drive_opts);
...
module_call_init(MODULE_INIT_OPTS);
error_init(argv[0]);
qemu_init_exec_dir(argv[0]);
//初始化CPU架构
qemu_init_arch_modules();
//初始化网络等
qemu_init_subsystems();
//第一次参数解析
optind = 1;
while (optind < argc) {
if (argv[optind][0] != '-') {
/* disk image */
optind++;
} else {
const QEMUOption *popt;
popt = lookup_opt(argc, argv, &optarg, &optind);
switch (popt->index) {
case QEMU_OPTION_nouserconfig:
userconfig = false;
break;
}
}
}
machine_opts_dict = qdict_new();
if (userconfig) {
qemu_read_default_config_file(&error_fatal);
}
//第二次参数解析
optind = 1;
for(;;) {
if (optind >= argc)
break;
if (argv[optind][0] != '-') {
loc_set_cmdline(argv, optind, 1);
drive_add(IF_DEFAULT, 0, argv[optind++], HD_OPTS);
} else {
const QEMUOption *popt;
popt = lookup_opt(argc, argv, &optarg, &optind);
if (!(popt->arch_mask & arch_type)) {
error_report("Option not supported for this target");
exit(1);
}
switch(popt->index) {
case QEMU_OPTION_cpu:
/* hw initialization will check this */
cpu_option = optarg;
break;
...
}
}
}
/*
* Clear error location left behind by the loop. Best done right after the loop. Do not insert code here!
*/
loc_set_none();
qemu_validate_options(machine_opts_dict);
qemu_process_sugar_options();
/*
* These options affect everything else and should be processed before daemonizing.
*/
qemu_process_early_options();
qemu_process_help_options();
qemu_maybe_daemonize(pid_file);
/*
* The trace backend must be initialized after daemonizing.
* trace_init_backends() will call st_init(), which will create the
* trace thread in the parent, and also register st_flush_trace_buffer()
* in atexit(). This function will force the parent to wait for the
* writeout thread to finish, which will not occur, and the parent
* process will be left in the host.
*/
if (!trace_init_backends()) {
exit(1);
}
trace_init_file();
qemu_init_main_loop(&error_fatal);
cpu_timers_init();
user_register_global_props();
replay_configure(icount_opts);
configure_rtc(qemu_find_opts_singleton("rtc"));
/* Transfer QemuOpts options into machine options */
parse_memory_options();
qemu_create_machine(machine_opts_dict);
suspend_mux_open();
//禁用默认设备
qemu_disable_default_devices();
//创建默认设备
qemu_create_default_devices();
//创建最近backends
qemu_create_early_backends();
//应用遗留参数
qemu_apply_legacy_machine_options(machine_opts_dict);
//应用其他参数
qemu_apply_machine_options(machine_opts_dict);
//释放machine_opts_dict
qobject_unref(machine_opts_dict);
phase_advance(PHASE_MACHINE_CREATED);
/*
* Note: uses machine properties such as kernel-irqchip, must run
* after qemu_apply_machine_options.
*/
configure_accelerators(argv[0]);
phase_advance(PHASE_ACCEL_CREATED);
/*
* Beware, QOM objects created before this point miss global and
* compat properties.
*
* Global properties get set up by qdev_prop_register_global(),
* called from user_register_global_props(), and certain option
* desugaring. Also in CPU feature desugaring (buried in
* parse_cpu_option()), which happens below this point, but may
* only target the CPU type, which can only be created after
* parse_cpu_option() returned the type.
*
* Machine compat properties: object_set_machine_compat_props().
* Accelerator compat props: object_set_accelerator_compat_props(),
* called from do_configure_accelerator().
*/
machine_class = MACHINE_GET_CLASS(current_machine);
if (!qtest_enabled() && machine_class->deprecation_reason) {
warn_report("Machine type '%s' is deprecated: %s",
machine_class->name, machine_class->deprecation_reason);
}
/*
* Note: creates a QOM object, must run only after global and compat properties have been set up.
*/
migration_object_init();
qemu_create_late_backends();
/* parse features once if machine provides default cpu_type */
current_machine->cpu_type = machine_class->default_cpu_type;
if (cpu_option) {
current_machine->cpu_type = parse_cpu_option(cpu_option);
}
/* NB: for machine none cpu_type could STILL be NULL here! */
qemu_resolve_machine_memdev();
parse_numa_opts(current_machine);
if (vmstate_dump_file) {
/* dump and exit */
module_load_qom_all();
dump_vmstate_json_to_file(vmstate_dump_file);
exit(0);
}
if (!preconfig_requested) {
qmp_x_exit_preconfig(&error_fatal);
}
//显示系统初始化,包括VNC和spice
qemu_init_displays();
accel_setup_post(current_machine);
os_setup_post();
resume_mux_open();
}
int qemu_main_loop(void)
{
int status = EXIT_SUCCESS;
#ifdef CONFIG_PROFILER
int64_t ti;
#endif
while (!main_loop_should_exit(&status)) {
#ifdef CONFIG_PROFILER
ti = profile_getclock();
#endif
main_loop_wait(false);
#ifdef CONFIG_PROFILER
dev_time += profile_getclock() - ti;
#endif
}
return status;
}
原文地址:https://blog.csdn.net/cai742925624/article/details/136917699
免责声明:本站文章内容转载自网络资源,如侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!