系列文章目录
第十七章 QEMU系统仿真的机器创建分析实例
文章目录
- 系列文章目录
-
- [第十七章 QEMU系统仿真的机器创建分析实例](#第十七章 QEMU系统仿真的机器创建分析实例)
- 前言
- 一、QEMU是什么?
- 二、QEMU系统仿真的机器创建分析实例
- 总结
前言
本文以 QEMU 8.2.2 为例,分析其作为系统仿真工具的工作过程,并为读者展示各种 QEMU 系统仿真的启动配置实例。
本文读者需要具备一定的 QEMU 系统仿真使用经验,并对 C 语言编程有一定了解。
一、QEMU是什么?
QEMU 是一个通用且开源的机器模拟器和虚拟机。
其官方主页是:https://www.qemu.org/
二、QEMU系统仿真的机器创建分析实例
1.系统仿真的命令行参数
QEMU 作为系统仿真工具,其入口代码在 system/main.c 文件中,初始化函数 qemu_init() 的实现在 system/vl.c 文件中。
前文完成创建目标机器的过程分析,本文将继续后续运行过程的分析,读者需要对 QEMU 系统启动过程的程序代码有所了解,相关内容可以参考《QEMU系统分析之启动篇》系列文章。
bash
..\qemu\8.2.2-qkd\qemu-system-x86_64.exe -cpu "Penryn" -M "q35,accel=whpx,smm=off" -m "6G" -display "sdl" -audio "sdl,model=hda" -vga "std" -L "data"
2.配置加速器
这部分代码在 system/vl.c 文件中,实现如下:
c
int qemu_init(int argc, char **argv)
{
...
configure_accelerators(argv[0]);
...
}
前文分析了应用当前机器设置项的过程,本文继续完成加速器的配置过程。
configure_accelerators()
函数 configure_accelerators() 代码如下:
c
static void configure_accelerators(const char *progname)
{
bool init_failed = false;
qemu_opts_foreach(qemu_find_opts("icount"),
do_configure_icount, NULL, &error_fatal);
if (QTAILQ_EMPTY(&qemu_accel_opts.head)) {
char **accel_list, **tmp;
if (accelerators == NULL) {
/* Select the default accelerator */
bool have_tcg = accel_find("tcg");
bool have_kvm = accel_find("kvm");
if (have_tcg && have_kvm) {
if (g_str_has_suffix(progname, "kvm")) {
/* If the program name ends with "kvm", we prefer KVM */
accelerators = "kvm:tcg";
} else {
accelerators = "tcg:kvm";
}
} else if (have_kvm) {
accelerators = "kvm";
} else if (have_tcg) {
accelerators = "tcg";
} else {
error_report("No accelerator selected and"
" no default accelerator available");
exit(1);
}
}
accel_list = g_strsplit(accelerators, ":", 0);
for (tmp = accel_list; *tmp; tmp++) {
/*
* Filter invalid accelerators here, to prevent obscenities
* such as "-machine accel=tcg,,thread=single".
*/
if (accel_find(*tmp)) {
qemu_opts_parse_noisily(qemu_find_opts("accel"), *tmp, true);
} else {
init_failed = true;
error_report("invalid accelerator %s", *tmp);
}
}
g_strfreev(accel_list);
} else {
if (accelerators != NULL) {
error_report("The -accel and \"-machine accel=\" options are incompatible");
exit(1);
}
}
if (!qemu_opts_foreach(qemu_find_opts("accel"),
do_configure_accelerator, &init_failed, &error_fatal)) {
if (!init_failed) {
error_report("no accelerator found");
}
exit(1);
}
if (init_failed && !qtest_chrdev) {
error_report("falling back to %s", current_accel_name());
}
if (icount_enabled() && !tcg_enabled()) {
error_report("-icount is not allowed with hardware virtualization");
exit(1);
}
}
首先,如果命令行参数中有 "icount" 则调用函数 do_configure_icount() 做配置。
do_configure_icount()
代码如下:
c
void icount_configure(QemuOpts *opts, Error **errp)
{
const char *option = qemu_opt_get(opts, "shift");
bool sleep = qemu_opt_get_bool(opts, "sleep", true);
bool align = qemu_opt_get_bool(opts, "align", false);
long time_shift = -1;
if (!option) {
if (qemu_opt_get(opts, "align") != NULL) {
error_setg(errp, "Please specify shift option when using align");
}
return;
}
if (align && !sleep) {
error_setg(errp, "align=on and sleep=off are incompatible");
return;
}
if (strcmp(option, "auto") != 0) {
if (qemu_strtol(option, NULL, 0, &time_shift) < 0
|| time_shift < 0 || time_shift > MAX_ICOUNT_SHIFT) {
error_setg(errp, "icount: Invalid shift value");
return;
}
} else if (icount_align_option) {
error_setg(errp, "shift=auto and align=on are incompatible");
return;
} else if (!icount_sleep) {
error_setg(errp, "shift=auto and sleep=off are incompatible");
return;
}
icount_sleep = sleep;
if (icount_sleep) {
timers_state.icount_warp_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL_RT,
icount_timer_cb, NULL);
}
icount_align_option = align;
if (time_shift >= 0) {
timers_state.icount_time_shift = time_shift;
icount_enable_precise();
return;
}
icount_enable_adaptive();
/*
* 125MIPS seems a reasonable initial guess at the guest speed.
* It will be corrected fairly quickly anyway.
*/
timers_state.icount_time_shift = 3;
/*
* Have both realtime and virtual time triggers for speed adjustment.
* The realtime trigger catches emulated time passing too slowly,
* the virtual time trigger catches emulated time passing too fast.
* Realtime triggers occur even when idle, so use them less frequently
* than VM triggers.
*/
timers_state.vm_clock_warp_start = -1;
timers_state.icount_rt_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL_RT,
icount_adjust_rt, NULL);
timer_mod(timers_state.icount_rt_timer,
qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL_RT) + 1000);
timers_state.icount_vm_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
icount_adjust_vm, NULL);
timer_mod(timers_state.icount_vm_timer,
qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
NANOSECONDS_PER_SECOND / 10);
}
static int do_configure_icount(void *opaque, QemuOpts *opts, Error **errp)
{
icount_configure(opts, errp);
return 0;
}
设置加速器顺序
代码如下:
c
static void configure_accelerators(const char *progname)
{
...
if (QTAILQ_EMPTY(&qemu_accel_opts.head)) {
char **accel_list, **tmp;
if (accelerators == NULL) {
/* Select the default accelerator */
bool have_tcg = accel_find("tcg");
bool have_kvm = accel_find("kvm");
if (have_tcg && have_kvm) {
if (g_str_has_suffix(progname, "kvm")) {
/* If the program name ends with "kvm", we prefer KVM */
accelerators = "kvm:tcg";
} else {
accelerators = "tcg:kvm";
}
} else if (have_kvm) {
accelerators = "kvm";
} else if (have_tcg) {
accelerators = "tcg";
} else {
error_report("No accelerator selected and"
" no default accelerator available");
exit(1);
}
}
accel_list = g_strsplit(accelerators, ":", 0);
for (tmp = accel_list; *tmp; tmp++) {
/*
* Filter invalid accelerators here, to prevent obscenities
* such as "-machine accel=tcg,,thread=single".
*/
if (accel_find(*tmp)) {
qemu_opts_parse_noisily(qemu_find_opts("accel"), *tmp, true);
} else {
init_failed = true;
error_report("invalid accelerator %s", *tmp);
}
}
g_strfreev(accel_list);
} else {
if (accelerators != NULL) {
error_report("The -accel and \"-machine accel=\" options are incompatible");
exit(1);
}
}
...
}
如果程序名后缀是 kvm 则设置 KVM 加速器优先,设置完加速器顺序后完成加速器的配置。
加速器配置通过函数 do_configure_accelerator() 来完成。
do_configure_accelerator()
代码如下:
c
static int do_configure_accelerator(void *opaque, QemuOpts *opts, Error **errp)
{
bool *p_init_failed = opaque;
const char *acc = qemu_opt_get(opts, "accel");
AccelClass *ac = accel_find(acc);
AccelState *accel;
int ret;
bool qtest_with_kvm;
if (!acc) {
error_setg(errp, QERR_MISSING_PARAMETER, "accel");
goto bad;
}
qtest_with_kvm = g_str_equal(acc, "kvm") && qtest_chrdev != NULL;
if (!ac) {
if (!qtest_with_kvm) {
error_report("invalid accelerator %s", acc);
}
goto bad;
}
accel = ACCEL(object_new_with_class(OBJECT_CLASS(ac)));
object_apply_compat_props(OBJECT(accel));
qemu_opt_foreach(opts, accelerator_set_property,
accel,
&error_fatal);
/*
* If legacy -singlestep option is set, honour it for TCG and
* silently ignore for any other accelerator (which is how this
* option has always behaved).
*/
if (opt_one_insn_per_tb) {
/*
* This will always succeed for TCG, and we want to ignore
* the error from trying to set a nonexistent property
* on any other accelerator.
*/
object_property_set_bool(OBJECT(accel), "one-insn-per-tb", true, NULL);
}
ret = accel_init_machine(accel, current_machine);
if (ret < 0) {
if (!qtest_with_kvm || ret != -ENOENT) {
error_report("failed to initialize %s: %s", acc, strerror(-ret));
}
goto bad;
}
return 1;
bad:
*p_init_failed = true;
return 0;
}
3.调试输出
首先,添加跟踪调试信息,修改后的代码如下:
c
static int do_configure_accelerator(void *opaque, QemuOpts *opts, Error **errp)
{
...
accel = ACCEL(object_new_with_class(OBJECT_CLASS(ac)));
HUEDBG("accel=0x%llx\n", (unsigned long long int)accel);
huedbg_dump_AccelClass(ac, 9);
...
}
static void configure_accelerators(const char *progname)
{
...
HUEDBG("accelerators=[%s]\n", accelerators);
accel_list = g_strsplit(accelerators, ":", 0);
...
}
int accel_init_machine(AccelState *accel, MachineState *ms)
{
AccelClass *acc = ACCEL_GET_CLASS(accel);
int ret;
HUEDBG("accel=0x%llx\n", (unsigned long long int)accel);
ms->accelerator = accel;
*(acc->allowed) = true;
ret = acc->init_machine(ms);
if (ret < 0) {
HUEDBG("\n");
ms->accelerator = NULL;
*(acc->allowed) = false;
object_unref(OBJECT(accel));
} else {
HUEDBG("\n");
object_set_accelerator_compat_props(acc->compat_props);
}
huedbg_dump_AccelClass(acc, 9);
return ret;
}
int qemu_init(int argc, char **argv)
{
...
/*
* Note: uses machine properties such as kernel-irqchip, must run
* after qemu_apply_machine_options.
*/
huedbg_flag = 1;
HUEDBG("\n");
configure_accelerators(argv[0]);
HUEDBG("\n");
huedbg_flag = 0;
phase_advance(PHASE_ACCEL_CREATED);
...
}
运行后,输出信息如下:
bash
[21096]../system/vl.c/qemu_init(2849):
[21096]../util/huedbg-option.c/huedbg_dump_QemuOptsList(183):<<<deep>>>=[9] list=[00007ff7ee3825c0]
[21096]../util/huedbg-option.c/huedbg_dump_QemuOptsList(185):name=[drive]
[21096]../util/huedbg-option.c/huedbg_dump_QemuOptsList(186):implied_opt_name=[(null)]
[21096]../util/huedbg-option.c/huedbg_dump_QemuOptsList(187):merge_lists=[0]
[21096]../util/huedbg-option.c/huedbg_dump_QemuOptsList(188):head=[00007ff7ee3825d8]
[21096]../util/huedbg-option.c/huedbg_dump_QemuOptsList(192):desc=[00007ff7ee3825e8]
[21096]../util/huedbg-option.c/huedbg_dump_QemuOptDesc(160):<<<deep>>>=[8] desc=[00007ff7ee3825e8]
[21096]../util/huedbg-option.c/huedbg_dump_QemuOptDesc(162):name=[(null)]
[21096]../util/huedbg-option.c/huedbg_dump_QemuOptDesc(163):type=[0]
[21096]../util/huedbg-option.c/huedbg_dump_QemuOptType(116):<<<deep>>>=[7] idx=[0]
[21096]../util/huedbg-option.c/huedbg_dump_QemuOptType(127):[0]=QEMU_OPT_STRING
[21096]../util/huedbg-option.c/huedbg_dump_QemuOptDesc(167):help=[(null)]
[21096]../util/huedbg-option.c/huedbg_dump_QemuOptDesc(168):def_value_str=[(null)]
[21096]../system/vl.c/qemu_init(2851):
[21096]../system/vl.c/qemu_init(3824):
[21096]../system/vl.c/configure_accelerators(2419):accelerators=[whpx]
[21096]../qom/object.c/object_class_by_name(1095):enter
[21096]../qom/object.c/type_table_lookup(103):lookup type(whpx-accel) in hash table
[21096]../qom/object.c/object_class_by_name(1105):class(whpx-accel) return
[21096]../qom/object.c/type_table_lookup(103):lookup type(accel) in hash table
[21096]../qom/object.c/type_get_parent(194):parent_type(accel)
[21096]../qom/object.c/object_class_by_name(1095):enter
[21096]../qom/object.c/type_table_lookup(103):lookup type(whpx-accel) in hash table
[21096]../qom/object.c/object_class_by_name(1105):class(whpx-accel) return
[21096]../qom/object.c/object_new_with_class(818):klass->type->name=[whpx-accel]
[21096]../qom/object.c/object_new_with_type(789):try type_initialize(whpx-accel)
[21096]../qom/object.c/object_new_with_type(799):obj(whpx-accel) alloc
[21096]../qom/object.c/object_new_with_type(808):try object_initialize_with_type(whpx-accel)
[21096]../qom/object.c/object_initialize_with_type(568):obj with type(whpx-accel) enter
[21096]../qom/object.c/object_initialize_with_type(576):mapping obj(whpx-accel).class with type(whpx-accel).class
[21096]../qom/object.c/object_initialize_with_type(579):try object_class_property_init_all(whpx-accel)
[21096]../qom/object.c/object_class_property_init_all(552):obj(whpx-accel) enter
[21096]../qom/object.c/object_class_property_iter_init(1440):objclass{whpx-accel} enter
[21096]../qom/object.c/object_class_get_parent(1130):enter
[21096]../qom/object.c/type_get_parent(194):parent_type(accel)
[21096]../qom/object.c/object_class_get_parent(1138):objclass(whpx-accel) has parent(accel)
[21096]../qom/object.c/object_class_get_parent(1141):objclass(whpx-accel) return
[21096]../qom/object.c/object_class_property_iter_init(1443):objclass{whpx-accel} return
[21096]../qom/object.c/object_class_property_init_all(555):prop name=[kernel-irqchip] type=[on|off|split] desc=[Configure WHPX in-kernel irqchip] init=[0000000000000000]
[21096]../qom/object.c/object_class_get_parent(1130):enter
[21096]../qom/object.c/type_get_parent(194):parent_type(object)
[21096]../qom/object.c/object_class_get_parent(1138):objclass(accel) has parent(object)
[21096]../qom/object.c/object_class_get_parent(1141):objclass(accel) return
[21096]../qom/object.c/object_class_get_parent(1130):enter
[21096]../qom/object.c/type_get_parent(196):no parent_type
[21096]../qom/object.c/object_class_get_parent(1134):objclass(object) has no parent return
[21096]../qom/object.c/object_class_property_init_all(555):prop name=[type] type=[string] desc=[(null)] init=[0000000000000000]
[21096]../qom/object.c/object_class_property_init_all(563):obj(whpx-accel) return
[21096]../qom/object.c/object_initialize_with_type(583):try object_init_with_type(whpx-accel)
[21096]../qom/object.c/object_init_with_type(416):obj->class->type->name=[whpx-accel] ti->name=[whpx-accel] enter
[21096]../qom/object.c/type_get_parent(194):parent_type(accel)
[21096]../qom/object.c/object_init_with_type(416):obj->class->type->name=[whpx-accel] ti->name=[accel] enter
[21096]../qom/object.c/type_get_parent(194):parent_type(object)
[21096]../qom/object.c/object_init_with_type(416):obj->class->type->name=[whpx-accel] ti->name=[object] enter
[21096]../qom/object.c/object_init_with_type(427):obj->class->type->name=[whpx-accel] ti->name=[object] return
[21096]../qom/object.c/object_init_with_type(427):obj->class->type->name=[whpx-accel] ti->name=[accel] return
[21096]../qom/object.c/object_init_with_type(423):name=[whpx-accel] ti->instance_init() before
[21096]../qom/object.c/object_init_with_type(425):name=[whpx-accel] ti->instance_init() after
[21096]../qom/object.c/object_init_with_type(427):obj->class->type->name=[whpx-accel] ti->name=[whpx-accel] return
[21096]../qom/object.c/object_initialize_with_type(585):try object_post_init_with_type(whpx-accel)
[21096]../qom/object.c/object_post_init_with_type(433):obj->class->type->name=[whpx-accel] ti->name=[whpx-accel] enter
[21096]../qom/object.c/type_get_parent(194):parent_type(accel)
[21096]../qom/object.c/object_post_init_with_type(433):obj->class->type->name=[whpx-accel] ti->name=[accel] enter
[21096]../qom/object.c/type_get_parent(194):parent_type(object)
[21096]../qom/object.c/object_post_init_with_type(433):obj->class->type->name=[whpx-accel] ti->name=[object] enter
[21096]../qom/object.c/object_post_init_with_type(444):return
[21096]../qom/object.c/object_post_init_with_type(444):return
[21096]../qom/object.c/object_post_init_with_type(444):return
[21096]../qom/object.c/object_initialize_with_type(587):obj(whpx-accel) return
[21096]../qom/object.c/object_new_with_type(812):obj(whpx-accel) return
[21096]../qom/object.c/type_table_lookup(103):lookup type(accel) in hash table
[21096]../qom/object.c/type_get_parent(194):parent_type(accel)
[21096]../system/vl.c/do_configure_accelerator(2353):accel=0x1dc0cf9d320
[21096]../util/huedbg-accel.c/huedbg_dump_AccelClass(76):<<<deep>>>=[9] ac=[000001dc0cf6d2e0]
[21096]../util/huedbg-accel.c/huedbg_dump_AccelClass(79):name=[WHPX]
[21096]../util/huedbg-accel.c/huedbg_dump_AccelClass(80):init_machine=[00007ff7edfa3d60]
[21096]../util/huedbg-accel.c/huedbg_dump_AccelClass(82):setup_post=[0000000000000000]
[21096]../util/huedbg-accel.c/huedbg_dump_AccelClass(83):has_memory=[0000000000000000]
[21096]../util/huedbg-accel.c/huedbg_dump_AccelClass(85):cpu_common_realize=[0000000000000000]
[21096]../util/huedbg-accel.c/huedbg_dump_AccelClass(86):cpu_common_unrealize=[0000000000000000]
[21096]../util/huedbg-accel.c/huedbg_dump_AccelClass(88):gdbstub_supported_sstep_flags=[0000000000000000]
[21096]../util/huedbg-accel.c/huedbg_dump_AccelClass(89):allowed=[00007ff7eefb19e9]
[21096]../util/huedbg-accel.c/huedbg_dump_AccelClass(91):*allowed=[0]
[21096]../util/huedbg-accel.c/huedbg_dump_AccelClass(93):compat_props=[0000000000000000]
[21096]../qom/object.c/type_table_lookup(103):lookup type(accel) in hash table
[21096]../qom/object.c/type_get_parent(194):parent_type(accel)
[21096]../accel/accel-system.c/accel_init_machine(40):accel=0x1dc0cf9d320
[21096]../qom/object.c/type_table_lookup(103):lookup type(machine) in hash table
[21096]../qom/object.c/type_get_parent(194):parent_type(object)
[21096]../qom/object.c/type_get_parent(196):no parent_type
[21096]../qom/object.c/type_get_parent(194):parent_type(generic-pc-machine)
[21096]../qom/object.c/type_get_parent(194):parent_type(x86-machine)
[21096]../qom/object.c/type_get_parent(194):parent_type(machine)
[21096]../target/i386/whpx/whpx-all.c/whpx_accel_init_machine(2778):mc=0x1dc0cf8b9f0,s=0x1dc0cf9d320,whpx=0x7ff7eefb1980
WHPX: setting APIC emulation mode in the hypervisor
Windows Hypervisor Platform accelerator is operational
[21096]../accel/accel-system.c/accel_init_machine(50):
[21096]../util/huedbg-accel.c/huedbg_dump_AccelClass(76):<<<deep>>>=[9] ac=[000001dc0cf6d2e0]
[21096]../util/huedbg-accel.c/huedbg_dump_AccelClass(79):name=[WHPX]
[21096]../util/huedbg-accel.c/huedbg_dump_AccelClass(80):init_machine=[00007ff7edfa3d60]
[21096]../util/huedbg-accel.c/huedbg_dump_AccelClass(82):setup_post=[0000000000000000]
[21096]../util/huedbg-accel.c/huedbg_dump_AccelClass(83):has_memory=[0000000000000000]
[21096]../util/huedbg-accel.c/huedbg_dump_AccelClass(85):cpu_common_realize=[0000000000000000]
[21096]../util/huedbg-accel.c/huedbg_dump_AccelClass(86):cpu_common_unrealize=[0000000000000000]
[21096]../util/huedbg-accel.c/huedbg_dump_AccelClass(88):gdbstub_supported_sstep_flags=[0000000000000000]
[21096]../util/huedbg-accel.c/huedbg_dump_AccelClass(89):allowed=[00007ff7eefb19e9]
[21096]../util/huedbg-accel.c/huedbg_dump_AccelClass(91):*allowed=[1]
[21096]../util/huedbg-accel.c/huedbg_dump_AccelClass(93):compat_props=[0000000000000000]
[21096]../system/vl.c/qemu_init(3826):
注意 AccelClass 信息变化如下:
bash
...
[21096]../system/vl.c/do_configure_accelerator(2353):accel=0x1dc0cf9d320
[21096]../util/huedbg-accel.c/huedbg_dump_AccelClass(76):<<<deep>>>=[9] ac=[000001dc0cf6d2e0]
[21096]../util/huedbg-accel.c/huedbg_dump_AccelClass(79):name=[WHPX]
[21096]../util/huedbg-accel.c/huedbg_dump_AccelClass(80):init_machine=[00007ff7edfa3d60]
[21096]../util/huedbg-accel.c/huedbg_dump_AccelClass(82):setup_post=[0000000000000000]
[21096]../util/huedbg-accel.c/huedbg_dump_AccelClass(83):has_memory=[0000000000000000]
[21096]../util/huedbg-accel.c/huedbg_dump_AccelClass(85):cpu_common_realize=[0000000000000000]
[21096]../util/huedbg-accel.c/huedbg_dump_AccelClass(86):cpu_common_unrealize=[0000000000000000]
[21096]../util/huedbg-accel.c/huedbg_dump_AccelClass(88):gdbstub_supported_sstep_flags=[0000000000000000]
[21096]../util/huedbg-accel.c/huedbg_dump_AccelClass(89):allowed=[00007ff7eefb19e9]
[21096]../util/huedbg-accel.c/huedbg_dump_AccelClass(91):*allowed=[0]
[21096]../util/huedbg-accel.c/huedbg_dump_AccelClass(93):compat_props=[0000000000000000]
...
[21096]../accel/accel-system.c/accel_init_machine(50):
[21096]../util/huedbg-accel.c/huedbg_dump_AccelClass(76):<<<deep>>>=[9] ac=[000001dc0cf6d2e0]
[21096]../util/huedbg-accel.c/huedbg_dump_AccelClass(79):name=[WHPX]
[21096]../util/huedbg-accel.c/huedbg_dump_AccelClass(80):init_machine=[00007ff7edfa3d60]
[21096]../util/huedbg-accel.c/huedbg_dump_AccelClass(82):setup_post=[0000000000000000]
[21096]../util/huedbg-accel.c/huedbg_dump_AccelClass(83):has_memory=[0000000000000000]
[21096]../util/huedbg-accel.c/huedbg_dump_AccelClass(85):cpu_common_realize=[0000000000000000]
[21096]../util/huedbg-accel.c/huedbg_dump_AccelClass(86):cpu_common_unrealize=[0000000000000000]
[21096]../util/huedbg-accel.c/huedbg_dump_AccelClass(88):gdbstub_supported_sstep_flags=[0000000000000000]
[21096]../util/huedbg-accel.c/huedbg_dump_AccelClass(89):allowed=[00007ff7eefb19e9]
[21096]../util/huedbg-accel.c/huedbg_dump_AccelClass(91):*allowed=[1]
[21096]../util/huedbg-accel.c/huedbg_dump_AccelClass(93):compat_props=[0000000000000000]
[21096]../system/vl.c/qemu_init(3826):
未调用 accel_init_machine() 前 *allowed = 0,调用后 *allowed = 1
总结
以上分析了系统初始化过程中加速器的配置过程。