DSP

再读uclinux-2008r1(bf561)内核存储区域管理(5):page初始化

2019-07-13 16:42发布

  快乐虾 http://blog.csdn.net/lights_joy/ lights@hb165.com      本文适用于 ADI bf561 DSP 优视BF561EVB开发板 uclinux-2008r1-rc8 (移植到vdsp5) Visual DSP++ 5.0    欢迎转载,但请保留作者信息    

1.1.1   page初始化

1.1.1.1             memmap_init

这个宏用于初始化mem_map中每个page的数据。 #define memmap_init(size, nid, zone, start_pfn) /      memmap_init_zone((size), (nid), (zone), (start_pfn), MEMMAP_EARLY) /*  * 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);      } } 调用此函数时size为整个SDRAM区域的页数,对于64M内存(限制为60M),其值为0x3bff。其余几个参数均为0 从这个函数可以看出,它依次对每个页的描述符page均进行了初始化。 pfn_to_page的定义如下: #define pfn_to_page(pfn)    virt_to_page(pfn_to_virt(pfn)) #define pfn_to_virt(pfn)    __va((pfn) << PAGE_SHIFT) #define __va(paddr)         phys_to_virt((unsigned long)(paddr)) #define phys_to_virt(vaddr) ((void *) (vaddr)) #define virt_to_page(addr)  (mem_map + (((unsigned long)(addr)-PAGE_OFFSET) >> PAGE_SHIFT)) 其实就是根据一个内存地址找到它所在页的描述结构page /*  * Setup the page count before being freed into the page allocator for  * the first time (boot or memory hotplug)  */ static inline void init_page_count(struct page *page) {      atomic_set(&page->_count, 1); } _count成员初始化为1 /*  * The atomic page->_mapcount, like _count, starts from -1:  * so that transitions both from it and to it can be tracked,  * using atomic_inc_and_test and atomic_add_negative(-1).  */ static inline void reset_page_mapcount(struct page *page) {      atomic_set(&(page)->_mapcount, -1); } 比较简单,将_mapcount值设置为1 #define SetPageReserved(page)    set_bit(PG_reserved, &(page)->flags) 从这里可以看出,初始化后的flags成员将带有唯一的标记PG_reserved    

1.1.1.2             set_page_links

此函数位于include/linux/mm.h static inline void set_page_links(struct page *page, enum zone_type zone,      unsigned long node, unsigned long pfn) {      set_page_zone(page, zone);      set_page_node(page, node);      set_page_section(page, pfn_to_section_nr(pfn)); } static inline void set_page_zone(struct page *page, enum zone_type zone) {      page->flags &= ~(ZONES_MASK << ZONES_PGSHIFT);      page->flags |= (zone & ZONES_MASK) << ZONES_PGSHIFT; } 在这个函数中,zone值为ZONE_DMA,即0值,因此这个函数相当于啥也不做。 static inline void set_page_section(struct page *page, unsigned long var_section) {      page->flags &= ~(SECTIONS_MASK << SECTIONS_PGSHIFT);      page->flags |= (var_section & SECTIONS_MASK) << SECTIONS_PGSHIFT; } #define pfn_to_section_nr(pfn) ((pfn) >> PFN_SECTION_SHIFT) #define PFN_SECTION_SHIFT 0 #define SECTIONS_PGSHIFT    (SECTIONS_PGOFF * (SECTIONS_WIDTH != 0)) #define SECTIONS_WIDTH      0 #define SECTIONS_MASK       ((1UL << SECTIONS_WIDTH) - 1) 这个函数也相当于什么都不做。 因而set_page_links这个函数相当于一个空函数。    

参考资料

uClinux2.6(bf561)中的CPLB(2008/2/19) uclinux2.6(bf561)中的bootmem分析(1):猜测(2008/5/9) uclinux2.6(bf561)中的bootmem分析(2):调用前的参数分析(2008/5/9) uclinux2.6(bf561)中的bootmem分析(3)init_bootmem_node(2008/5/9) uclinux2.6(bf561)中的bootmem分析(4)alloc_bootmem_pages(2008/5/9) uclinux2.6(bf561)内核中的paging_init(2008/5/12) uclinux-2008r1(bf561)内核的icache支持(1):寄存器配置初始化(2008/5/16) uclinux-2008r1(bf561)内核的icache支持(2)icplb_table的生成(2008/5/16) uclinux-2008r1(bf561)内核的icache支持(3)__fill_code_cplbtab(2008/5/16) uclinux-2008r1(bf561)内核的icache支持(4):换页问题(2008/5/16) 再读uclinux-2008r1(bf561)内核中的bootmem(2008/6/3) uclinux-2008r1(bf561)内核中与存储管理相关的几个全局变量(2008/6/4) uclinux-2008r1(bf561)内核存储区域初探(2008/6/4) uclinux-2008r1(bf561)内核中的zonelist初始化(2008/6/5) uclinux-2008r1(bf561)内核中内存管理相关的几个结构体(2008/6/5) 再读内核存储管理(1):相关的全局变量(2008/6/17) 再读内核存储管理(2):相关的数据结构(2008/6/17) 再读内核存储管理(3)bootmem分配策略(2008/6/17) 再读内核存储管理(4):存储区域管理(2008/6/17) 再读内核存储管理(5)buddy算法(2008/6/17) 再读内核存储管理(6):高速缓存的应用(2008/6/17) 再读内核存储管理(7)icache支持(2008/6/17) 再读内核存储管理(8):片内SRAM的使用(2008/6/17) 初读SLAB(2008/6/26) 三读bootmem(2008/7/24) 再读uclinux-2008r1(bf561)内核存储区域管理(1):相关数据结构(2008/7/25) 再读uclinux-2008r1(bf561)内核存储区域管理(2):可用页表初始化(2008/7/25) 再读uclinux-2008r1(bf561)内核存储区域管理(3):zone初始化(2008-7-25) 再读uclinux-2008r1(bf561)内核存储区域管理(4):zonelist初始化(2008-7-25)