网站公告列表

  没有公告

加入收藏
设为首页
联系本站
您现在的位置: AnalogCN安诺电子 >> 文章 >> 技术交流 >> 文章正文
  uclinux-2008r1(bf561)内核中与存储管理相关的几个全局变量           ★★★ 【字体:
uclinux-2008r1(bf561)内核中与存储管理相关的几个全局变量
作者:快乐虾    文章来源:http://blog.csdn.net/lights_joy    点击数:    更新时间:2008-6-4    
1.1.1   _ramstart, _ramend, _rambase
这三个全局变量的定义在head.s文件中:
/*
 * Set up the usable of RAM stuff. Size of RAM is determined then
 * an initial stack set up at the end.
 */
 
.align 4
__rambase:
.long   0
__ramstart:
.long   0
__ramend:
.long   0
为了在C文件中使用它们,在include/asm/bfin-global.h中做了一个声明:
extern unsigned long _ramstart, _ramend, _rambase;
然后在setup_arch函数中对它们进行了初始化:
     _ramend = CONFIG_MEM_SIZE * 1024 * 1024;
     _ramstart = (unsigned long)__bss_stop;
     _rambase = (unsigned long)_stext;
在这里__bss_stop是在ldf文件中定义:
      bsz_sdram ZERO_INIT
      {
               …
         INPUT_SECTION_ALIGN(4)
         . = (. + 3) / 4 * 4;
               ___bss_stop = .;
               __end = .;
               
      } > MEM_SDRAM
而bsz_sdram是内核中的最后一个段,因此_ramstart将指向内核之后的第一个可用字节。
_stext也是在ldf文件中定义的一个变量:
        .text
        {
         INPUT_SECTION_ALIGN(4)
         . = (. + 3) / 4 * 4;
               __text = .;
               _text = .;
               __stext = .;
               …….
 
         INPUT_SECTION_ALIGN(4)
         . = (. + 3) / 4 * 4;
               __etext = .;
        } > MEM_SDRAM_TEXT
而.text是内核中排在最前面的一个段,因此_rambase将指向内核的起始位置。
在这里还需要注意_ramend的定义,虽然在这里给它赋了一个固定的值,但是通过引导程序设定启动参数可以进行更改,如引导程序使用
mem=32m
的时候,将会在parse_cmdline_early函数中触发下面的代码:
              if (!memcmp(to, "mem=", 4)) {
                   to += 4;
                   memsize = memparse(to, &to);
                   if (memsize)
                       _ramend = memsize;
 
              } else if (!memcmp(to, "max_mem=", 8)) {
….
从而将这个值更改。
1.1.2   memory_startmemory_end
这两个全局变量几乎都是同时使用的,它们的定义在arch/blackfin/kernel/setup.c中:
unsigned long memory_start, memory_end, physical_mem_end;
在setup_arch函数中对它们做了初始化工作:
     memory_start = PAGE_ALIGN(_ramstart);
/* to align the pointer to the (next) page boundary */
#define PAGE_ALIGN(addr)    (((addr)+PAGE_SIZE-1)&PAGE_MASK)
memory_start指向内核结束的位置,但是向上做了页对齐(4K)
     /* by now the stack is part of the init task */
     memory_end = _ramend - DMA_UNCACHED_REGION;
#if defined(CONFIG_DMA_UNCACHED_2M)
# define DMA_UNCACHED_REGION (2 * 1024 * 1024)
#elif defined(CONFIG_DMA_UNCACHED_1M)
# define DMA_UNCACHED_REGION (1024 * 1024)
#else
# define DMA_UNCACHED_REGION (0)
#endif
memory_end指向可用物理内存的最高位置。
当没有启用MTD的时候,还有下面一段代码:
 
#if (defined(CONFIG_BFIN_ICACHE) && ANOMALY_05000263)
     /* Due to a Hardware Anomaly we need to limit the size of usable
      * instruction memory to max 60MB, 56 if HUNT_FOR_ZERO is on
      * 05000263 - Hardware loop corrupted when taking an ICPLB exception
      */
#if (defined(CONFIG_DEBUG_HUNT_FOR_ZERO))
     if (memory_end >= 56 * 1024 * 1024)
         memory_end = 56 * 1024 * 1024;
#else
     if (memory_end >= 60 * 1024 * 1024)
         memory_end = 60 * 1024 * 1024;
#endif                 /* CONFIG_DEBUG_HUNT_FOR_ZERO */
     printk(KERN_NOTICE "Warning: limiting memory to %liMB due to hardware anomaly 05000263\n", memory_end >> 20);
#endif                 /* ANOMALY_05000263 */
此时,由于ANOMALY_05000263的缘故,memory_end将被限制为60M,即0x03c0 0000。
#if !defined(CONFIG_MTD_UCLINUX)
     memory_end -= SIZE_4K; /*In case there is no valid CPLB behind memory_end make sure we don't get to close*/
#endif
由此,memory_end的值变为0x03bf f000。且不再改变。
当启用了MTD的时候,memory_end将指向物理内存减去RAMDISK大小的位置。
1.1.3   nr_kernel_pages与nr_all_pages
这两个值的定义都在mm/page_alloc.c中:
unsigned long __meminitdata nr_kernel_pages;
unsigned long __meminitdata nr_all_pages;
free_area_init_core这个初始化函数中对它们赋初值:
static void __meminit free_area_init_core(struct pglist_data *pgdat,
         unsigned long *zones_size, unsigned long *zholes_size)
{
   
    
     for (j = 0; j < MAX_NR_ZONES; j++) {
         struct zone *zone = pgdat->node_zones + j;
         unsigned long size, realsize, memmap_pages;
 
         // size = realsize = SDRAM的页表数量,对M SDRAM,其值为x3fff
         size = zone_spanned_pages_in_node(nid, j, zones_size);
         realsize = size - zone_absent_pages_in_node(nid, j,
                                     zholes_size);
 
         /*
          * Adjust realsize so that it accounts for how much memory
          * is used by this zone for memmap. This affects the watermark
          * and per-cpu initialisations
          */
         memmap_pages = (size * sizeof(struct page)) >> PAGE_SHIFT;
         if (realsize >= memmap_pages) {
              realsize -= memmap_pages;
              printk(KERN_DEBUG
                   " %s zone: %lu pages used for memmap\n",
                   zone_names[j], memmap_pages);
         } else
              printk(KERN_WARNING
                   " %s zone: %lu pages exceeds realsize %lu\n",
                   zone_names[j], memmap_pages, realsize);
 
         /* Account for reserved pages */
         // dma_reserve的值可以从引导程序导入,在此为0
         if (j == 0 && realsize > dma_reserve) {
              realsize -= dma_reserve;
              printk(KERN_DEBUG " %s zone: %lu pages reserved\n",
                       zone_names[0], dma_reserve);
         }
 
         // is_highmem_idx恒为
         if (!is_highmem_idx(j))
              nr_kernel_pages += realsize;
         nr_all_pages += realsize;
          .
 
     }
}
从上述代码可以看出,这两个值都表示可用的页的数量,其表示的内存范围从0到60M,不包含page数组所占用的页。对于64MSDRAM(实际限制为60M),不启用MTD的情况,其值为0x3b6a。
1.1.4   mem_map
这个全局变量的定义在mm/nommu.c中:
struct page *mem_map;
在内核中每个4K的页都有一个struct page与之相对应,而mem_map就是指向这个page数组的头指针。
它的初始化由alloc_node_mem_map完成:
static void __init_refok alloc_node_mem_map(struct pglist_data *pgdat)
{
     /* 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);
     }
     /*
      * 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;
     }
}
从这个函数可以看出,它的值与pglist_data中的node_mem_map成员相同。
在这里pgdat指向全局唯一的pglist_data:
extern struct pglist_data contig_page_data;
pgdat->node_start_pfn的值为0。
pgdat->node_spanned_pages的值为整个SDRAM中的页(4K)数量。
1.1.5   contig_page_data
内核支持所谓的NUMA结构,它将整个系统的存储空间分成几个不连续的节点,每个节点用一个pglist_data进行描述,再将这些节点放在一个链表中,但在BF561系统内核中定义了一个叫NODE_DATA的宏,它的定义在include/linux/mmzone.h中
extern struct pglist_data contig_page_data;
#define NODE_DATA(nid)      (&contig_page_data)
从这个定义可以看出,在内核中实际只有一个pglist_data。即contig_page_data。
文章录入:admin    责任编辑:admin 
  • 上一篇文章:

  • 下一篇文章:
  • 发表评论】【加入收藏】【告诉好友】【打印此文】【关闭窗口
    最新热点 最新推荐 相关文章
    前置放大器在移动医疗服务系
    便携式多通道大容量生理信号
    防腐监测仪的设计与应用
    基于AD1674的酶标仪的设计
    基于C/S模式的JRTPLIB库的测
    ffmpeg与jrtplib相结合应用
    blackfin模拟摄像头驱动中的
    可编程逻辑在数字信号处理系
    发现VDSP4.5一个BUG:单步调
    VDSP5.0双核工程下sml3中的变
      网友评论:(只显示最新10条。评论内容只代表网友观点,与本站立场无关!)
    版权所有:AnalogCN安诺电子 湘ICP备06016315号