uclinux-2008R1.5-RC3(bf561)到VDSP5的移植(55):CONFIG_FLAT_NODE_MEM_MAP

rev 0.1

快乐虾

http://blog.csdn.net/lights_joy/

[email protected]

本文适用于

ADI bf561 DSP

优视BF561EVB开发板

uclinux-2008r1.5-rc3(smp patch)

Visual DSP++ 5.0(update 5)

欢迎转载,但请保留作者信息

出现一个问题,在运行到memmap_init_zone函数时,内核跑飞了。跟踪下代码:

/*

* Initially all pages are reserved - free ones are freed

* up by free_all_bootmem() once the early boot process is

* done. Non-atomic initialization, single-pass.

*/

void __meminit memmap_init_zone(unsigned long size, int nid, unsigned long zone,

unsigned long start_pfn, enum memmap_context context)

{

struct page *page;

unsigned long end_pfn = start_pfn + size;

unsigned long pfn;

for (pfn = start_pfn; pfn < end_pfn; pfn++) {

/*

* There can be holes in boot-time mem_map[]s

* handed to this function. They do not

* exist on hotplugged memory.

*/

if (context == MEMMAP_EARLY) {

if (!early_pfn_valid(pfn))

continue;

if (!early_pfn_in_nid(pfn, nid))

continue;

}

page = pfn_to_page(pfn);

set_page_links(page, zone, nid, pfn);

init_page_count(page);

reset_page_mapcount(page);

SetPageReserved(page);

INIT_LIST_HEAD(&page->lru);

#ifdef WANT_PAGE_VIRTUAL

/* The shift won't overflow because ZONE_NORMAL is below 4G. */

if (!is_highmem_idx(zone))

set_page_address(page, __va(pfn << PAGE_SHIFT));

#endif

}

}

发现下面这几行代码没有生成相应的汇编代码:

if (context == MEMMAP_EARLY) {

if (!early_pfn_valid(pfn))

continue;

if (!early_pfn_in_nid(pfn, nid))

continue;

}

于是想是不是编译器出毛病了。但仔细查了下,发现两个定义:

#ifndef early_pfn_valid

#define early_pfn_valid(pfn) (1)

#endif

#ifdef CONFIG_NODES_SPAN_OTHER_NODES

#define early_pfn_in_nid(pfn, nid) (early_pfn_to_nid(pfn) == (nid))

#else

#define early_pfn_in_nid(pfn, nid) (1)

#endif

原来这两个宏都返回常量1,编译器直接把这几行代码给优化掉了。

再设条件断点,发现这个循环在执行2378之后就挂了。因为这一段代码修改的变量只有page结构体,开始怀疑是page指针的问题,看一下page指针的值:0x00012940,落在.text这个段内,相当于改变了程序代码,想不出错都不行!

page指针来源于这一行:

page = pfn_to_page(pfn);

pfn_to_page这个宏接受一个page序号做为参数,并取得这个序号所代表的page结构体指针。这个转换需要用到一个叫mem_map的全局变量。

在内核中每个4K的页都有一个struct page与之相对应,而mem_map就是指向这个page数组的头指针。

查一下mem_map的值,为0!也就是说,mem_map没有初始化!难怪出错!

mem_map初始化的地方在这里:

static void __init_refok alloc_node_mem_map(struct pglist_data *pgdat)

{

/* Skip empty nodes */

if (!pgdat->node_spanned_pages)

return;

#ifdef CONFIG_FLAT_NODE_MEM_MAP

/* ia64 gets its own node_mem_map, before this, without bootmem */

if (!pgdat->node_mem_map) {

unsigned long size, start, end;

struct page *map;

/*

* The zone's endpoints aren't required to be MAX_ORDER

* aligned but the node_mem_map endpoints must be in order

* for the buddy allocator to function correctly.

*/

start = pgdat->node_start_pfn & ~(MAX_ORDER_NR_PAGES - 1);

end = pgdat->node_start_pfn + pgdat->node_spanned_pages;

end = ALIGN(end, MAX_ORDER_NR_PAGES);

size = (end - start) * sizeof(struct page);

map = alloc_remap(pgdat->node_id, size);

if (!map)

map = alloc_bootmem_node(pgdat, size);

pgdat->node_mem_map = map + (pgdat->node_start_pfn - start);

}

#ifndef CONFIG_NEED_MULTIPLE_NODES

/*

* With no DISCONTIG, the global mem_map is just set as node 0's

*/

if (pgdat == NODE_DATA(0)) {

mem_map = NODE_DATA(0)->node_mem_map;

#ifdef CONFIG_ARCH_POPULATES_NODE_MAP

if (page_to_pfn(mem_map) != pgdat->node_start_pfn)

mem_map -= pgdat->node_start_pfn;

#endif /* CONFIG_ARCH_POPULATES_NODE_MAP */

}

#endif

#endif /* CONFIG_FLAT_NODE_MEM_MAP */

}

当没有定义CONFIG_FLAT_NODE_MEM_MAP的时候,mem_map的确是不会初始化的!

知道问题的所在,解决就很简单了,直接在config.h加上这个宏定义即可。

1 参考资料

uclinux-2008R1.5-RC3(bf561)VDSP5的移植(50).spinlock.text(2009-1-24)

uclinux-2008R1.5-RC3(bf561)VDSP5的移植(51)CONFIG_LOG_BUF_SHIFT(2009-1-24)

uclinux-2008R1.5-RC3(bf561)VDSP5的移植(52)__ebss_l1(2009-1-28)

uclinux-2008R1.5-RC3(bf561)VDSP5的移植(53)ARRAY_SIZE(2009-1-30)

uclinux-2008R1.5-RC3(bf561)VDSP5的移植(54)MEM_SDRAM_BANKx(2009-2-1)

你可能感兴趣的:(.net,Blog,UP)