1. Linux 內存的meminfo 獲取過程

1. Linux 內存的大小獲取過程

硬件:tiny4412

軟件:linux3.0.86,uboot-tiny4412

目的:梳理linux start-kernel階段,獲取內核大小的過程,並將內存bank個數,start ,size信息,放入meminfo中

tiny4412平臺,傳遞內存的信息,是通過 u-boot,傳遞tag的方式來傳遞內存的大小的,而不是通過dtb的方式。 

【start_kernel()->setup_arch()】

    //首先判斷是否從fdt中,獲取machine desc 
	mdesc = setup_machine_fdt(__atags_pointer);
	if (!mdesc)
        //以tags的方式,獲取machine desc
		mdesc = setup_machine_tags(machine_arch_type);
static struct machine_desc * __init setup_machine_tags(unsigned int nr)
{
	struct tag *tags = (struct tag *)&init_tags;
	struct machine_desc *mdesc = NULL, *p;
	char *from = default_command_line;

	init_tags.mem.start = PHYS_OFFSET;

	/*
	 * locate machine in the list of supported machines.
	 */
	for_each_machine_desc(p)
		if (nr == p->nr) {
			printk("Machine: %s\n", p->name);
			mdesc = p;
			break;
		}
...
	if (tags->hdr.tag == ATAG_CORE) {
		if (meminfo.nr_banks != 0)
			squash_mem_tags(tags);
		save_atags(tags);
		parse_tags(tags);
	}

首先會通過for_each_machine_desc查找對應的 machine ID。 

machine ID 是放置在 .arch.info.init 這個section的數據。 通過MACHINE_START 註冊的machine將會放在在 .arch.info.init 這個section 中。

以tag的形式傳遞過來的數據 ,不同的數據有不同的tag及進行標識

#define ATAG_CORE    0x54410001
#define ATAG_MEM    0x54410002
#define ATAG_CMDLINE    0x54410003
#define ATAG_RDIMG    0x54410004
parse_tags(tags);

static void __init parse_tags(const struct tag *t)
{
       //編譯傳遞過來的tag
	    for (; t->hdr.size; t = tag_next(t))
	    	if (!parse_tag(t))
			printk(KERN_WARNING
				"Ignoring unrecognised tag 0x%08x\n",
				t->hdr.tag);
}

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

	return t < &__tagtable_end;
}

在setup.c 中,會通過__tagtable 註冊以下執行的函數,方式在taglist.init這個setction中,

struct tagtable {
	u32	tag;
	int	(*parse)(struct tag *);
};


#define __tag __used __attribute__((__section__(".taglist.init")))
#define __tagtable(tag, fn)						\
	static struct tagtable __tagtable_##fn __tag = { tag, fn 

static int __init parse_tag_mem32(const struct tag *tag)
{
	return arm_add_memory(tag->u.mem.start, tag->u.mem.size);
}

__tagtable(ATAG_MEM, parse_tag_mem32);

有u-boot傳遞過來的帶有ATAG_MEM 的信息,將會執行 arm_add_memory函數

int __init arm_add_memory(phys_addr_t start, unsigned long size)
{
	struct membank *bank = &meminfo.bank[meminfo.nr_banks];

	if (meminfo.nr_banks >= NR_BANKS) {
		printk(KERN_CRIT "NR_BANKS too low, "
			"ignoring memory at 0x%08llx\n", (long long)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;

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

	meminfo.nr_banks++;
	return 0;
}

arm_add_memory函數,拿到由u-boot傳遞過來的哪個bank的start地址和長度,放到變量meminfo中。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章