浅析armlinux-setup_arch()->memtable_init()函数5-2
文章来源:http://gliethttp.cublog.cn
建议首先参考《浅析armlinux2_4_19启动程序[head-armv.s文件]》[http://gliethttp.cublog.cn]
//---------------------------------------- //arch/arm/mm/Mm-armv.c->memtable_init() void __init memtable_init(struct meminfo *mi) { struct map_desc *init_maps, *p, *q; unsigned long address = 0; int i; //请参考《浅析armlinux-setup_arch()->alloc_bootmem_low_pages()函数5-1》[http://gliethttp.cublog.cn] init_maps = p = alloc_bootmem_low_pages(PAGE_SIZE);//返回申请到的清0的大小为PAGE_SIZE的物理内存页对应虚拟地址 for (i = 0; i < mi->nr_banks; i++) { if (mi->bank[i].size == 0) continue; //将node对应的信息,存储到init_maps结构体中 p->physical = mi->bank[i].start; p->virtual = __phys_to_virt(p->physical); p->length = mi->bank[i].size; p->domain = DOMAIN_KERNEL; p->prot_read = 0; p->prot_write = 1; p->cacheable = 1; p->bufferable = 1; p ++; }
#ifdef FLUSH_BASE//对于我的开发板不存在该项,false p->physical = FLUSH_BASE_PHYS; p->virtual = FLUSH_BASE; p->length = PGDIR_SIZE; p->domain = DOMAIN_KERNEL; p->prot_read = 1; p->prot_write = 0; p->cacheable = 1; p->bufferable = 1; p ++; #endif
#ifdef FLUSH_BASE_MINICACHE//对于我的开发板不存在该项,false p->physical = FLUSH_BASE_PHYS + PGDIR_SIZE; p->virtual = FLUSH_BASE_MINICACHE; p->length = PGDIR_SIZE; p->domain = DOMAIN_KERNEL; p->prot_read = 1; p->prot_write = 0; p->cacheable = 1; p->bufferable = 0; p ++; #endif //对4G空间的第一级页目录进行初始化 //我的at91rm9200开发板,q->virtual=0xC0000000,q->length=0x02000000=32M //所以清理 //0x00000000~0xC0000000虚拟内存空间一级页目录 //0xC2000000~0xFFFFFFFF虚拟内存空间一级页目录 //同时创建 //0xC0000000~0xC2000000对应的虚拟内存空间一级页目录 //可参考《linux2.4.19下__ioremap函数中remap_area_pages虚拟地址映射建立函数的代码分析》[http://gliethttp.cublog.cn] q = init_maps; do { if (address < q->virtual || q == p) { //清除swapper_pg_dir[address>>20]对应的1M页目录项,一共4k个1M页目录项,4k*1M=4G[gliethttp] //请参考《浅析armlinux-setup_arch()->clear_mapping()函数5-2-1》[http://gliethttp.cublog.cn] clear_mapping(address); address += PGDIR_SIZE; } else { //请参考《浅析armlinux-setup_arch()->create_mapping()函数5-2-2》[http://gliethttp.cublog.cn] create_mapping(q);//创建该node对应的虚拟地址空间与物理空间的2级小页映射 address = q->virtual + q->length; address = (address + PGDIR_SIZE - 1) & PGDIR_MASK; q ++;//加到q==p为止 } } while (address != 0); /* * Create a mapping for the machine vectors at virtual address 0 * or 0xffff0000. We should always try the high mapping. */ //对init/main.c->start_kernel()->trap_init()中映射到高端虚拟地址0xffff0000的中断向量表 //进行相应物理内存映射分配 init_maps->physical = virt_to_phys(init_maps);//把init_maps对应的4k空间作为中断向量表的物理存储区 init_maps->virtual = vectors_base();//init_maps->virtual=0xffff0000 init_maps->length = PAGE_SIZE; init_maps->domain = DOMAIN_USER; init_maps->prot_read = 0; init_maps->prot_write = 0; init_maps->cacheable = 1; init_maps->bufferable = 0; create_mapping(init_maps);//完成虚拟地址0xffff0000到物理内存地址virt_to_phys(init_maps)的映射 //此句执行完毕之后,init_maps对应的4k空间已经被中断向量表专用 //对于中断向量表的建立情况,请参考我的另一篇浅析文章《浅析arm-linux中断vector向量表的建立流程》[http://gliethttp.cublog.cn] }
|
阅读(1931) | 评论(0) | 转发(1) |