内核 machine_desc table 信息在哪里?

Where is kernel machine_desc table information?

我正在尝试了解设备树的工作原理。

根据内核文档,它们在 arm 架构中的使用方式如下:

In the majority of cases, the machine identity is irrelevant, and the kernel will instead select setup code based on the machine’s core CPU or SoC. On ARM for example, setup_arch() in arch/arm/kernel/setup.c will call setup_machine_fdt() in arch/arm/kernel/devtree.c which searches through the machine_desc table and selects the machine_desc which best matches the device tree data. It determines the best match by looking at the ‘compatible’ property in the root device tree node, and comparing it with the dt_compat list in struct machine_desc (which is defined in arch/arm/include/asm/mach/arch.h if you’re curious).

The ‘compatible’ property contains a sorted list of strings starting with the exact name of the machine, followed by an optional list of boards it is compatible with sorted from most compatible to least.

我在dts文件中找到了machine_desc与兼容参数集对比的相关源码:

const struct machine_desc * __init setup_machine_fdt(void *dt_virt)
{
    const struct machine_desc *mdesc, *mdesc_best = NULL;

#if defined(CONFIG_ARCH_MULTIPLATFORM) || defined(CONFIG_ARM_SINGLE_ARMV7M)
    DT_MACHINE_START(GENERIC_DT, "Generic DT based system")
        .l2c_aux_val = 0x0,
        .l2c_aux_mask = ~0x0,
    MACHINE_END

    mdesc_best = &__mach_desc_GENERIC_DT;
#endif

    if (!dt_virt || !early_init_dt_verify(dt_virt))
        return NULL;

    mdesc = of_flat_dt_match_machine(mdesc_best, arch_get_next_mach);

    if (!mdesc) {
        const char *prop;
        int size;
        unsigned long dt_root;

        early_print("\nError: unrecognized/unsupported "
                "device tree compatible list:\n[ ");

        dt_root = of_get_flat_dt_root();
        prop = of_get_flat_dt_prop(dt_root, "compatible", &size);
        while (size > 0) {
            early_print("'%s' ", prop);
            size -= strlen(prop) + 1;
            prop += strlen(prop) + 1;
        }
        early_print("]\n\n");

        dump_machine_table(); /* does not return */
    }

    /* We really don't want to do this, but sometimes firmware provides buggy data */
    if (mdesc->dt_fixup)
        mdesc->dt_fixup();

    early_init_dt_scan_nodes();

    /* Change machine number to match the mdesc we're using */
    __machine_arch_type = mdesc->nr;

    return mdesc;
}

但是,我没有找到machine_desc table定义。

如果我想阅读所有 machine_desc,我在哪里可以找到它?

TL;DR - 机器描述是通过构建不同的源文件并将其链接到内核中构建的。因此每个机器源文件都会在 table.

中添加一个条目

table基于arch/arm/kernel/vmlinux.lds.S(或相关架构链接器文件)。它是用宏 MACHINE_STARTMACHINE_END 构建的。这会在目标文件的 'arch.info.init' 部分放置一个结构。所有这些对象都被链接器组合在一起。这形成了table。因此,它是通过使用 MACHINE_STARTMACHINE_END 宏链接不同的源文件来构建的。因此,它不存在于一处。

但是,您可以使用 git grep -A10 MACHINE_START 来获得相当不错的列表。此命令运行良好,通常它是文件中的最后一件事,因此可能只打印五六行。或者您可以编写初始化代码,通过打印 machine_desc 条目来转储 table。

也就是说,table 并不太有趣,因为它只是在不同时间调用的函数指针。大多数将是 NULL,因为它使用了指定的初始值设定项。

相关:Control to 'dt_machine_start' on Android