Chinaunix首页 | 论坛 | 博客
  • 博客访问: 111873
  • 博文数量: 64
  • 博客积分: 186
  • 博客等级: 入伍新兵
  • 技术积分: 120
  • 用 户 组: 普通用户
  • 注册时间: 2012-02-24 17:11
文章分类

全部博文(64)

文章存档

2014年(54)

2013年(2)

2012年(8)

我的朋友

分类: LINUX

2014-06-04 14:52:06

浅析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]
}

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