快乐虾
http://blog.csdn.net/lights_joy/
本文适用于
ADI bf561 DSP
优视BF561EVB开发板
uclinux-2008r1-rc8 (移植到vdsp5)
Visual DSP++ 5.0
欢迎转载,但请保留作者信息
这个宏用于初始化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。
此函数位于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 )