DSP

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

2019-07-13 15:56发布

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)