【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


总结

以上分析了系统初始化过程中加速器的配置过程。

相关推荐
鸿蒙开天组●2 分钟前
鸿蒙进阶篇-属性动画-animateTo&转场动画
华为·harmonyos
XZHOUMIN40 分钟前
网易博客旧文-----XCODE离线帮助文件使用的补充说明
ide·macos·xcode
醇氧1 小时前
ab (Apache Bench)的使用
linux·学习·centos·apache
moneyxjj2 小时前
Linux各种解压命令汇总
linux·运维·服务器
白白♛~2 小时前
网络管理之---3种网络模式配置
linux·服务器·网络
天下皆白_唯我独黑2 小时前
超好用shell脚本NuShell mac安装
macos
山城码农笑松哥2 小时前
Mac解压包安装MongoDB8并设置launchd自启动
mongodb·macos
GOTXX2 小时前
NAT、代理服务与内网穿透技术全解析
linux·网络·人工智能·计算机网络·智能路由器
bjxiaxueliang2 小时前
一文详解MacOS使用VSCode搭建SpringBoot+Gradle开发环境
spring boot·vscode·macos
芋头莎莎2 小时前
STM32 51单片机设计半导体制冷片温控设计
stm32·嵌入式硬件·51单片机