Full Analysis of QEMU Source Code 14 - Introduction to QOM (3)

Continued from the previous article: Full Analysis of QEMU Source Code 13 - Introduction to QOM (2)

References for the content of this article:

"Interesting Talk about Linux Operating System " —— Liu Chao, Geek Time

" QEMU /KVM" source code analysis and application - Li Qiang, Machinery Industry Press

Thank you very much!

The last book talked about the first part of QOM - the registration of types, which is halfway through, and this article will continue.

Soon after entering the main function of QEMU, the function module_call_init was called with MODULE_INIT_QOM as a parameter (also mentioned in the above document). So when is module_call_init(MODULE_INIT_QOM) called? Search for this keyword in the QEMU source code qemu-7.1.0 (version 7.1.0 source code), there will be many places, so which one is the main function called soon?

Full analysis of QEMU source code 7 —— In the main function of QEMU, I once talked about the main function, which is in softmmu/main.c. In order to facilitate understanding and deepen the impression, the source code is posted again:

int qemu_main(int argc, char **argv, char **envp)
{
    int status;

    qemu_init(argc, argv, envp);
    status = qemu_main_loop();
    qemu_cleanup();

    return status;
}

#ifndef CONFIG_COCOA
int main(int argc, char **argv)
{
    return qemu_main(argc, argv, NULL);
}
#endif

The location of the main function is in the softmmu directory, so theoretically you should find the module_call_init (MODULE_INIT_QOM) in the same directory from the above keyword search results, it is most likely what we are looking for. There is indeed a call in runstate.c in the softmmu directory, the code is as follows:

void qemu_init_subsystems(void)
{
    Error *err = NULL;

    os_set_line_buffering();

    module_call_init(MODULE_INIT_TRACE);

    qemu_init_cpu_list();
    qemu_init_cpu_loop();
    qemu_mutex_lock_iothread();

    atexit(qemu_run_exit_notifiers);

    module_call_init(MODULE_INIT_QOM);
    module_call_init(MODULE_INIT_MIGRATION);

    runstate_init();
    precopy_infrastructure_init();
    postcopy_infrastructure_init();
    monitor_init_globals();

    if (qcrypto_init(&err) < 0) {
        error_reportf_err(err, "cannot initialize crypto: ");
        exit(1);
    }

    os_setup_early_signal_handling();

    bdrv_init_with_whitelist();
    socket_init();
}

The module_call_init(MODULE_INIT_QOM); is called in the qemu_init_subsystems function. The qemu_init_subsystems function is called in the qemu_init function. The code snippet is as follows (in softmmu/vl.c):

void qemu_init(int argc, char **argv, char **envp)
{
    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);
    qemu_add_drive_opts(&qemu_common_drive_opts);
    qemu_add_drive_opts(&qemu_drive_opts);
    qemu_add_drive_opts(&bdrv_runtime_opts);

    ……

    qemu_init_subsystems();

    ……

}

This is very clear, the function call chain is: main() -> qemu_main() -> qemu_init() -> qemu_init_subsystems() -> module_call_init(MODULE_INIT_QOM).

Having figured this out, back to the topic. For easier understanding, paste the module_call_init function code (in util/module.c):

void module_call_init(module_init_type type)
{
    ModuleTypeList *l;
    ModuleEntry *e;

    if (modules_init_done[type]) {
        return;
    }

    l = find_type(type);

    QTAILQ_FOREACH(e, l, node) {
        e->init();
    }

    modules_init_done[type] = true;
}

The module_call_int function executes the init function of each ModuleEntry on the init_type_list[MODULE_INIT_QOM] linked list.

Still taking edu as an example, the init function of this type is pci_edu_register_types (a sentence in hw/misc/edu.c mentioned above: type_init(pci_edu_register_types)), this function is in hw/misc/edu.c, the code is as follows :

static void pci_edu_register_types(void)
{
    static InterfaceInfo interfaces[] = {
        { INTERFACE_CONVENTIONAL_PCI_DEVICE },
        { },
    };
    static const TypeInfo edu_info = {
        .name          = TYPE_PCI_EDU_DEVICE,
        .parent        = TYPE_PCI_DEVICE,
        .instance_size = sizeof(EduState),
        .instance_init = edu_instance_init,
        .class_init    = edu_class_init,
        .interfaces = interfaces,
    };

    type_register_static(&edu_info);
}
type_init(pci_edu_register_types)

The only job of the pci_edu_register_types function is to construct a TypeInfo type of edu_info, and call type_register_static with it as a parameter.

See next time for more details and analysis.

Guess you like

Origin blog.csdn.net/phmatthaus/article/details/131959530