现在的位置: 首页 > 综合 > 正文

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

2013年09月20日 ⁄ 综合 ⁄ 共 3817字 ⁄ 字号 评论关闭

rev 0.1

 

快乐虾

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

lights@hb165.com

 

本文适用于

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)

 

 

抱歉!评论已关闭.