Home > OS >  Where is kernel machine_desc table information?
Where is kernel machine_desc table information?

Time:05-28

I'm trying to understand how devicetrees work.

According to the kernel documentation, they are used, in arm architecture, in the following manner:

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.

I found the source code related to the comparison of machine_desc to the compatible parameter set in the dts file:

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;
}

However, I didn't find machine_desc table definition.

If I'd like to read all machine_desc, Where can I find it?

CodePudding user response:

TL;DR - The machine description is built by building and linking different source files into the kernel. So each machine source file adds an entry into the table.


The table is based in arch/arm/kernel/vmlinux.lds.S (or relevant architecture linker file). It is built with the macros MACHINE_START and MACHINE_END. This throws a structure in the 'arch.info.init' sections of the linker file. All of these get globbed together by the linker. This forms the table. So, it is constructed by linking different source files with the MACHINE_START and MACHINE_END macros. So, it doesn't exist in one place.

However, you can use git grep -A10 MACHINE_START to get a fairly good list. This command works well, as typically, it is the last thing in the file so only five or six lines may print. Or you could write init code to dump the table by printing the machine_desc entries.

That said, the table is not too interesting as it is just function pointers to call at different times. The majority will be NULL as it used designated initializers.

Related: Control to 'dt_machine_start' on Android

  • Related