how meminfo was got&used

/*                                                                                                                     
 *  linux/arch/arm/kernel/head-common.S                                                                                
 *                                                                                                                     
 *  Copyright (C) 1994-2002 Russell King                                                                               
 *  Copyright (c) 2003 ARM Limited                                                                                     
 *  All Rights Reserved                                                                                                
 *                                                                                                                     
 * This program is free software; you can redistribute it and/or modify                                                
 * it under the terms of the GNU General Public License version 2 as                                                   
 * published by the Free Software Foundation.                                                                          
 *                                                                                                                     
 */

#define ATAG_CORE 0x54410001
#define ATAG_CORE_SIZE ((2*4 + 3*4) >> 2)
#define ATAG_CORE_SIZE_EMPTY ((2*4) >> 2)

        .align  2
        .type   __switch_data, %object
__switch_data:
        .long   __mmap_switched
        .long   __data_loc                      @ r4
        .long   _data                           @ r5
        .long   __bss_start                     @ r6
        .long   _end                            @ r7
        .long   processor_id                    @ r4
        .long   __machine_arch_type             @ r5
        .long   __atags_pointer                 @ r6     //the tag structure from passed by u-boot
        .long   cr_alignment                    @ r7
        .long   init_thread_union + THREAD_START_SP @ sp

*** arch/arm/include/asm/setup.h:
#define __tag __used __attribute__((__section__(".taglist.init")))
#define __tagtable(tag, fn) \
static struct tagtable __tagtable_##fn __tag = { tag, fn }


*** arch/arm/kernel/setup.c:
<global>[626]                  __tagtable(ATAG_CORE, parse_tag_core);
<global>[633]                  __tagtable(ATAG_MEM, parse_tag_mem32);
<global>[663]                  __tagtable(ATAG_MEM_RESERVED, parse_tag_mem32_reserved);
<global>[692]                  __tagtable(ATAG_MEM_LOW_POWER, parse_tag_mem32_low_power);
<global>[719]                  __tagtable(ATAG_VIDEOTEXT, parse_tag_videotext);
<global>[730]                  __tagtable(ATAG_RAMDISK, parse_tag_ramdisk);
<global>[739]                  __tagtable(ATAG_SERIAL, parse_tag_serialnr);
<global>[747]                  __tagtable(ATAG_REVISION, parse_tag_revision);
<global>[755]                  __tagtable(ATAG_CMDLINE, parse_tag_cmdline);

//the seconde parameter in macro __tag_table(tag, fn) is just 
//the member function pointer "parse".
struct tagtable {
    __u32 tag;
    int (*parse)(const struct tag *);
};


*** arch/arm/kernel/setup.c:
--------------------------------------------------------------------
...
unsigned int __atags_pointer __initdata;
...

void __init setup_arch(char **cmdline_p)
{
    struct tag *tags = (struct tag *)&init_tags;
    struct machine_desc *mdesc;
    char *from = default_command_line;


    unwind_init();


    setup_processor();
    mdesc = setup_machine(machine_arch_type);
    machine_name = mdesc->name;


    if (mdesc->soft_reboot)
        reboot_setup("s");


    if (__atags_pointer)
        tags = phys_to_virt(__atags_pointer);  //the tag table was pickup by the kernel here !!!
    else if (mdesc->boot_params)
        tags = phys_to_virt(mdesc->boot_params);


    /*                                                                                                                 
     * If we have the old style parameters, convert them to                                                            
     * a tag list.                                                                                                     
     */
    if (tags->hdr.tag != ATAG_CORE)
        convert_to_tag_list(tags);
    if (tags->hdr.tag != ATAG_CORE)
        tags = (struct tag *)&init_tags;


    if (mdesc->fixup)
        mdesc->fixup(mdesc, tags, &from, &meminfo);


    if (tags->hdr.tag == ATAG_CORE) {
        if (meminfo.nr_banks != 0)
            squash_mem_tags(tags);
        save_atags(tags);
        parse_tags(tags);                       //tagtable was get parsed here
    }


    init_mm.start_code = (unsigned long) _text;
    init_mm.end_code   = (unsigned long) _etext;
    init_mm.end_data   = (unsigned long) _edata;
    init_mm.brk    = (unsigned long) _end;


    memcpy(boot_command_line, from, COMMAND_LINE_SIZE);
    boot_command_line[COMMAND_LINE_SIZE-1] = '\0';
    parse_cmdline(cmdline_p, from);
    paging_init(mdesc);
    request_standard_resources(&meminfo, mdesc);


#ifdef CONFIG_SMP
    smp_init_cpus();
#endif


    cpu_init();
    tcm_init();


    /*                                                                                                                 
     * Set up various architecture-specific pointers                                                                   
     */
    init_arch_irq = mdesc->init_irq;
    system_timer = mdesc->timer;
    init_machine = mdesc->init_machine;


#ifdef CONFIG_VT
#if defined(CONFIG_VGA_CONSOLE)
    conswitchp = &vga_con;
#elif defined(CONFIG_DUMMY_CONSOLE)
    conswitchp = &dummy_con;
#endif
#endif
    early_trap_init();
}


/*                                                                                                                     
 * Parse all tags in the list, checking both the global and architecture                                               
 * specific tag tables.                                                                                                
 */
static void __init parse_tags(const struct tag *t)
{
    for (; t->hdr.size; t = tag_next(t))
        if (!parse_tag(t))
            printk(KERN_WARNING
                "Ignoring unrecognised tag 0x%08x\n",
                t->hdr.tag);
}

/*                                                                                                                     
 * Scan the tag table for this tag, and call its parse function.                                                       
 * The tag table is built by the linker from all the __tagtable                                                        
 * declarations.                                                                                                       
 */
static int __init parse_tag(const struct tag *tag)
{
    extern struct tagtable __tagtable_begin, __tagtable_end;
    struct tagtable *t;

    for (t = &__tagtable_begin; t < &__tagtable_end; t++)
        if (tag->hdr.tag == t->tag) {
            t->parse(tag);                //each function registerd with __tagtable() macro get called here
            break;
        }

    return t < &__tagtable_end;
}


//for meminfo:
*** arch/arm/kernel/setup.c:
--------------------------------------------------------------
static int __init parse_tag_mem32(const struct tag *tag)
{
    return arm_add_memory(tag->u.mem.start, tag->u.mem.size);  //this function init meminfo.bank[]
}

__tagtable(ATAG_MEM, parse_tag_mem32);


static int __init arm_add_memory(unsigned long start, unsigned long size)
{
    struct membank *bank = &meminfo.bank[meminfo.nr_banks]; //meminfo.bank[] array traversed here


    if (meminfo.nr_banks >= NR_BANKS) {
        printk(KERN_CRIT "NR_BANKS too low, "
            "ignoring memory at %#lx\n", start);
        return -EINVAL;
    }


    /*                                                                                                                 
     * Ensure that start/size are aligned to a page boundary.                                                          
     * Size is appropriately rounded down, start is rounded up.                                                        
     */
    size -= start & ~PAGE_MASK;
    bank->start = PAGE_ALIGN(start);
    bank->size  = size & PAGE_MASK;
    bank->node  = PHYS_TO_NID(start);


    /*                                                                                                                 
     * Check whether this memory region has non-zero size or                                                           
     * invalid node number.                                                                                            
     */
    if (bank->size == 0 || bank->node >= MAX_NUMNODES)
        return -EINVAL;


    meminfo.nr_banks++;
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值