Chinaunix首页 | 论坛 | 博客
  • 博客访问: 206698
  • 博文数量: 81
  • 博客积分: 55
  • 博客等级: 民兵
  • 技术积分: 26
  • 用 户 组: 普通用户
  • 注册时间: 2012-02-21 17:54
文章分类
文章存档

2018年(1)

2017年(1)

2016年(5)

2015年(23)

2014年(51)

我的朋友

分类: LINUX

2014-02-28 10:56:34

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

3. 全部内存初始化完毕,可以用cache和buddy分配内存。

相关常量定义:
 26 #define NODE_DATA(nid)      (node_data[nid])

 782 extern struct pglist_data contig_page_data;
 783 #define NODE_DATA(nid)      (&contig_page_data)
 784 #define NODE_MEM_MAP(nid)   mem_map

4714 struct pglist_data __refdata contig_page_data = {
4716     .bdata = &bootmem_node_data[0]
4718 };

38 bootmem_data_t bootmem_node_data[MAX_NUMNODES] __initdata;//MAX_NUMNODES=0

 31 typedef struct bootmem_data {
 32     unsigned long node_min_pfn;
 33     unsigned long node_low_pfn;
 34     void *node_bootmem_map;
 35     unsigned long last_end_off;
 36     unsigned long hint_idx;
 37     struct list_head list;
 38 } bootmem_data_t;

 609 typedef struct pglist_data {
 610     struct zone node_zones[MAX_NR_ZONES];
 611     struct zonelist node_zonelists[MAX_ZONELISTS];
 612     int nr_zones;
 613 #ifdef CONFIG_FLAT_NODE_MEM_MAP /* means !SPARSEMEM */
 614     struct page *node_mem_map;
 615 #ifdef CONFIG_CGROUP_MEM_RES_CTLR
 616     struct page_cgroup *node_page_cgroup;
 617 #endif
 618 #endif
 619 #ifndef CONFIG_NO_BOOTMEM
 620     struct bootmem_data *bdata;
 621 #endif
 622 #ifdef CONFIG_MEMORY_HOTPLUG
 623     /*
 624      * Must be held any time you expect node_start_pfn, node_present_pages
 625      * or node_spanned_pages stay constant.  Holding this will also
 626      * guarantee that any pfn_valid() stays that way.
 627      *
 628      * Nests above zone->lock and zone->size_seqlock.
 629      */
 630     spinlock_t node_size_lock;
 631 #endif
 632     unsigned long node_start_pfn;
 633     unsigned long node_present_pages; /* total number of physical pages */
 634     unsigned long node_spanned_pages; /* total size of physical page
 635                          range, including holes */
 636     int node_id;
 637     wait_queue_head_t kswapd_wait;
 638     struct task_struct *kswapd;
 639     int kswapd_max_order;
 640 } pg_data_t;

 576 struct zonelist {
 577     struct zonelist_cache *zlcache_ptr;          // NULL or &zlcache = NULL
 578     struct zoneref _zonerefs[MAX_ZONES_PER_ZONELIST + 1];//MAX_ZONES_PER_ZONELIST=4
 579 #ifdef CONFIG_NUMA
 580     struct zonelist_cache zlcache;               // optional ...
 581 #endif
 582 };

 554 struct zoneref {
 555     struct zone *zone;  /* Pointer to actual zone */
 556     int zone_idx;       /* zone_idx(zoneref->zone) */
 557 };

内存初始化步骤:
1. start_kernel---->setup_arch->pageing_init
                |-->setup_per_cpu_areas
                |-->build_all_zonelists
                |-->mem_init
                 -->setup_per_cpu_pageset


start_kernel---->setup_arch->pageing_init代码如下:
  1. 273 /*
  2. 274 * paging_init() sets up the page tables - in fact we've already done this.
  3. 275 */
  4. 276 void __init paging_init(void)
  5. 277 {
  6. 278     unsigned long total_ram = memblock_phys_mem_size();
  7. 279     phys_addr_t top_of_ram = memblock_end_of_DRAM();
  8. 280     unsigned long max_zone_pfns[MAX_NR_ZONES];
  9. 281
  10. 282 #ifdef CONFIG_PPC32
  11. 283     unsigned long v = __fix_to_virt(__end_of_fixed_addresses - 1);
  12. 284     unsigned long end = __fix_to_virt(FIX_HOLE);
  13. 285
  14. 286     for (; v < end; v += PAGE_SIZE)
  15. 287     map_page(v, 0, 0); /* XXX gross */
  16. 288 #endif
  17. 289
  18. 290 #ifdef CONFIG_HIGHMEM
  19. 291     map_page(PKMAP_BASE, 0, 0); /* XXX gross */
  20. 292     pkmap_page_table = virt_to_kpte(PKMAP_BASE);
  21. 293
  22. 294     kmap_pte = virt_to_kpte(__fix_to_virt(FIX_KMAP_BEGIN));
  23. 295     kmap_prot = PAGE_KERNEL;
  24. 296 #endif /* CONFIG_HIGHMEM */
  25. 297
  26. 298     printk(KERN_DEBUG "Top of RAM: 0x%llx, Total RAM: 0x%lx\n",
  27. 299            (unsigned long long)top_of_ram, total_ram);
  28. 300     printk(KERN_DEBUG "Memory hole size: %ldMB\n",
  29. 301            (long int)((top_of_ram - total_ram) >> 20));
  30. 302     memset(max_zone_pfns, 0, sizeof(max_zone_pfns));
  31. 303 #ifdef CONFIG_HIGHMEM
  32. 304     max_zone_pfns[ZONE_DMA] = lowmem_end_addr >> PAGE_SHIFT;
  33. 305     max_zone_pfns[ZONE_HIGHMEM] = top_of_ram >> PAGE_SHIFT;
  34. 306 #else
  35. 307     max_zone_pfns[ZONE_DMA] = top_of_ram >> PAGE_SHIFT;
  36. 308 #endif
  37. 309     free_area_init_nodes(max_zone_pfns);
  38. 310
  39. 311     mark_nonram_nosave();
  40. 312 }
  41. 313 #endif /* ! CONFIG_NEED_MULTIPLE_NODES */
378-280:计算整个内存的大小,此处为:0x8000 0000
282-288: 映射临时映射空间,也称固定映射
290-196:映射高端内存PTE
307:最为重要,该函数清空bitmap区,把所有页设为保留。

                |-->setup_per_cpu_areas
该函数当非SMP情况使用,此处为空。
                |-->build_all_zonelists
函数代码为:


  1. 3031 void build_all_zonelists(void *data)
  2. 3032 {
  3. 3033     set_zonelist_order();
  4. 3034
  5. 3035     if (system_state == SYSTEM_BOOTING) {
  6. 3036         __build_all_zonelists(NULL);
  7. 3037         mminit_verify_zonelist();
  8. 3038         cpuset_init_current_mems_allowed();
  9. 3039     } else {
  10. 3040     /* we have to stop all cpus to guarantee there is no user
  11. 3041     of zonelist */
  12. 3042     stop_machine(__build_all_zonelists, data, NULL);
  13. 3043     /* cpuset refresh routine should be here */
  14. 3044     }
  15. 3045     vm_total_pages = nr_free_pagecache_pages();
  16. 3046 /*
  17. 3047 * Disable grouping by mobility if the number of pages in the
  18. 3048 * system is too low to allow the mechanism to work. It would be
  19. 3049 * more accurate, but expensive to check per-zone. This check is
  20. 3050 * made on memory-hotadd so a system can start with mobility
  21. 3051 * disabled and enable it later
  22. 3052 */
  23. 3053      if (vm_total_pages < (pageblock_nr_pages * MIGRATE_TYPES))
  24. 3054          page_group_by_mobility_disabled = 1;
  25. 3055      else
  26. 3056          page_group_by_mobility_disabled = 0;
  27. 3057
  28. 3058      printk("Built %i zonelists in %s order, mobility grouping %s. "
  29. 3059               "Total pages: %ld\n",
  30. 3060      nr_online_nodes,
  31. 3061      zonelist_order_name[current_zonelist_order],
  32. 3062      page_group_by_mobility_disabled ? "off" : "on",
  33. 3063      vm_total_pages);
  34. 3064 #ifdef CONFIG_NUMA
  35. 3065      printk("Policy zone: %s\n", zone_names[policy_zone]);
  36. 3066 #endif
  37. 3067 }
函数中:__build_all_zonelists函数建立了zone链表,当一个zone不能满足当前分配时会根据此链表来找到下一个可以分配的zone。当有多个节点时,建立后的结果为:
b2->b1->b0->a2->a1->a0 (b=node1,a=node0,2=highmem, 1=normal, 0=dma)

|-->mem_init函数代码为:
  1. 526 static void __init mm_init(void)
  2. 527 {
  3. 532     page_cgroup_init_flatmem();
  4. 533     mem_init();
  5. 534     kmem_cache_init();
  6. 535     pgtable_cache_init();
  7. 536     vmalloc_init();
  8. 537 }
532:为空函数
533:函数执行完毕后, mem_init_done = 1;即buddy系统分配内存内可以使用了。
534:用来初始化slab和cache,函数执行完后slab可以使用,可以分配少于1页的内存了。
535:空函数
536:vmalloc空间可以正常使用了。
整个内存的布局为:
Kernel virtual memory layout:
  * 0xfffcf000..0xfffff000  : fixmap
  * 0xff800000..0xffc00000  : highmem PTEs
  * 0xff7d8000..0xff800000  : early ioremap
  * 0xf1000000..0xff7d8000  : vmalloc & ioremap









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