----------------------------------------
硬件: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使用位图来分配页,每次分配都从头开始扫描位,找到满足条件的连续空页。
阅读(3383) | 评论(0) | 转发(3) |