Chinaunix首页 | 论坛 | 博客
  • 博客访问: 791603
  • 博文数量: 118
  • 博客积分: 2067
  • 博客等级: 大尉
  • 技术积分: 1751
  • 用 户 组: 普通用户
  • 注册时间: 2009-07-17 14:27
文章存档

2016年(1)

2013年(1)

2012年(3)

2011年(26)

2010年(47)

2009年(40)

分类: LINUX

2011-03-31 16:33:28

----------------------------------------
硬件:E500v2内核PowerPC ,linux版本:2.6.35
----------------------------------------

bootmem初始化完--->buddy完成前。结束标志为mem_init_done = 1
start_kernel->setup_arch->do_init_bootmem:

179 #ifndef CONFIG_NEED_MULTIPLE_NODES
180 void __init do_init_bootmem(void)
181 {
182     unsigned long i;
183     unsigned long start, bootmap_pages;
184     unsigned long total_pages;
185     int boot_mapsize;
186
187     max_low_pfn = max_pfn = memblock_end_of_DRAM() >> PAGE_SHIFT;
188     total_pages = (memblock_end_of_DRAM() - memstart_addr) >> PAGE_SHIFT;
189 #ifdef CONFIG_HIGHMEM
190     total_pages = total_lowmem >> PAGE_SHIFT;
191     max_low_pfn = lowmem_end_addr >> PAGE_SHIFT;
192 #endif

此处的计算都是从第一阶段的memblock而来,到192行之后各变量值为:
max_low_pfn: 30000
max_pfn: 80000
total_pages: 30000
因为板子上含有highmem,所以total_pages和max_low_pfn都进行了调整,这些值只反映低端内存的情况。

194     /*
195      * Find an area to use for the bootmem bitmap.  Calculate the size of
196      * bitmap required as (Total Memory) / PAGE_SIZE / BITS_PER_BYTE.
197      * Add 1 additional page in case the address isn't page-aligned.
198      */
199     bootmap_pages = bootmem_bootmap_pages(total_pages);
200
201     start = memblock_alloc(bootmap_pages << PAGE_SHIFT, PAGE_SIZE);
202
203     min_low_pfn = MEMORY_START >> PAGE_SHIFT;
204     boot_mapsize = init_bootmem_node(NODE_DATA(0), start >> PAGE_SHIFT, min_low_pfn, max_low_pfn);

199:分配管理内存页所需要的内存,其中每页用1Bit表示,所以当有total_pages页时,大小为:
(Total Memory) / PAGE_SIZE / BITS_PER_BYTE。其中BITS_PER_BYTE=8
201:分配该BITMAP区域所占用的空间,还有是第一阶段的内存分配方法,返回的是内存物理地址。
204:初始化node节点,初始化bitmap区为0xff,即占用状态,返回bitmap区大小。
通过计算可知道,bitmap空间占6页,即:0x30000/4K/8bit=6page.

206     /* Add active regions with valid PFNs */
207     for (i = 0; i < memblock.memory.cnt; i++) {
208         unsigned long start_pfn, end_pfn;
209         start_pfn = memblock.memory.region[i].base >> PAGE_SHIFT;
210         end_pfn = start_pfn + memblock_size_pages(&memblock.memory, i);
211         add_active_range(0, start_pfn, end_pfn);
212     }

此循环只会执行一次,因为由第1阶段可知memblock.memory.cnt为1。
其中:start_pfn=0, end_pfn=80000,把这段内存pfn加入early_node_map[MAX_ACTIVE_REGIONS=32]中,如果有多个不连续段内存,会另入到不同的early_node_map中,最多32个段。early_node_map为临时使用,最终所占空间会被释放。

217 #ifdef CONFIG_HIGHMEM
218     free_bootmem_with_active_regions(0, lowmem_end_addr >> PAGE_SHIFT);
219
220     /* reserve the sections we're already using */
221     for (i = 0; i < memblock.reserved.cnt; i++) {
222         unsigned long addr = memblock.reserved.region[i].base +
223                      memblock_size_bytes(&memblock.reserved, i) - 1;
224         if (addr < lowmem_end_addr)
225             reserve_bootmem(memblock.reserved.region[i].base,
226                     memblock_size_bytes(&memblock.reserved, i),
227                     BOOTMEM_DEFAULT);
228         else if (memblock.reserved.region[i].base < lowmem_end_addr) {
229             unsigned long adjusted_size = lowmem_end_addr -
230                       memblock.reserved.region[i].base;
231             reserve_bootmem(memblock.reserved.region[i].base,
232                     adjusted_size, BOOTMEM_DEFAULT);
233         }
234     }
235 #else
236     free_bootmem_with_active_regions(0, max_pfn);
237
238     /* reserve the sections we're already using */
239     for (i = 0; i < memblock.reserved.cnt; i++)
240         reserve_bootmem(memblock.reserved.region[i].base,
241                 memblock_size_bytes(&memblock.reserved, i),
242                 BOOTMEM_DEFAULT);
243
244 #endif

由于存在highmem,所以执行上半段。
218:释放early_node_map数组标识的lowmem的内存段,即把0~30000的PFN对应的bitmap区中相应位置0.其中每bit标识一页,LOG信息为:
bootmem::mark_bootmem_node nid=0 start=0 end=30000 reserve=0 flags=0
bootmem::__free nid=0 start=0 end=30000
212:开始的for循环是把已经分配的内存页标记为1,即已在使用。LOG信息如下:
bootmem::mark_bootmem_node nid=0 start=0 end=6b1 reserve=1 flags=0
bootmem::__reserve nid=0 start=0 end=6b1 flags=0
bootmem::mark_bootmem_node nid=0 start=ffa end=ffd reserve=1 flags=0
bootmem::__reserve nid=0 start=ffa end=ffd flags=0
bootmem::mark_bootmem_node nid=0 start=2fbc4 end=2fbdf reserve=1 flags=0
bootmem::__reserve nid=0 start=2fbc4 end=2fbdf flags=0
bootmem::mark_bootmem_node nid=0 start=2fbdf end=30000 reserve=1 flags=0
bootmem::__reserve nid=0 start=2fbdf end=30000 flags=0
bootmem::mark_bootmem_node nid=0 start=2fbe4 end=30000 reserve=1 flags=0
bootmem::__reserve nid=0 start=2fbe4 end=30000 flags=0
只标记了低端内存,高端内存未做标记,即:
reserved[0x5]  0x000000007ffff000 - 0x000000007fffffff, 0x1000 bytes

246     sparse_memory_present_with_active_regions(0);
247
248     init_bootmem_done = 1;
249 }

246:空函数
248:标识bootmem初始化完成,此后可以使用使用bootmem来分配内存页了。bootmem使用位图来分配页,每次分配都从头开始扫描位,找到满足条件的连续空页。


















阅读(3323) | 评论(0) | 转发(3) |
给主人留下些什么吧!~~