Linux arm 启动 c语言部分详解第二讲Start kernel setupa.docx
- 文档编号:1991039
- 上传时间:2023-05-02
- 格式:DOCX
- 页数:8
- 大小:18.62KB
Linux arm 启动 c语言部分详解第二讲Start kernel setupa.docx
《Linux arm 启动 c语言部分详解第二讲Start kernel setupa.docx》由会员分享,可在线阅读,更多相关《Linux arm 启动 c语言部分详解第二讲Start kernel setupa.docx(8页珍藏版)》请在冰点文库上搜索。
Linuxarm启动c语言部分详解第二讲Startkernelsetupa
[原创]Linuxarm启动c语言部分详解第二讲(Startkernel->setup_a
Writtenbyleeming这一讲是主要讲setup_arch中那个没有解释的函数解释完毕,完成setup_arch的函数,好让我们的start_kernel继续下去。
/**paging_init()setsupthepagetables,initialisesthezonememory*maps,andsetsupthezeropage,badpageandbadpagetables.*这部分的主要工作建立页表,初始化内存。
*/void__initpaging_init(structmeminfo*mi,structmachine_desc*mdesc){ void*zero_page;//这个函数主要是用来建立各种类型的页表选项(比如内存是MEMORY类型,设备室DEVICE,中断向量表是HIGH_VECTORS) build_mem_type_table();{ structcachepolicy*cp; //获取cp15处理器的c1寄存器位 unsignedintcr=get_cr(); unsignedintuser_pgprot,kern_pgprot; //获取处理器架构版本 intcpu_arch=cpu_architecture(); inti; //根据处理器版本号调整cache政策,不是写缓冲区的政策#ifdefined(CONFIG_CPU_DCACHE_DISABLE) if(cachepolicy>CPOLICY_BUFFERED) cachepolicy=CPOLICY_BUFFERED;#elifdefined(CONFIG_CPU_DCACHE_WRITETHROUGH) if(cachepolicy>CPOLICY_WRITETHROUGH) cachepolicy=CPOLICY_WRITETHROUGH;#endif if(cpu_arch if(cachepolicy>=CPOLICY_WRITEALLOC) cachepolicy=CPOLICY_WRITEBACK; ecc_mask=0;//因为v5前的处理器的一级描述符没有定义第9位作为保护标志位 } if(cpu_arch //mem_types是一个全局数组arch/arm/mm-armv.c,里面有所有类型 for(i=0;i //prot_l1prot_sect都是一级描述符的意思 //将一级描述符的第4位置1 if(mem_types.prot_l1) mem_types.prot_l1|=PMD_BIT4; if(mem_types.prot_sect) mem_types.prot_sect|=PMD_BIT4; } } //我们的cachepolicy是3,因此相应的配置如下 // .policy ="writeback", // .cr_mask =0, // .pmd =PMD_SECT_WB, // .pte =PTE_BUFFERABLE|PTE_CACHEABLE, cp=&cache_policies[cachepolicy]; //kern_pgprotuser_pgprot是内核和用户空间的二级页表描述符 kern_pgprot=user_pgprot=cp->pte; //以下删除了非v4t架构的高版本代码 for(i=0;i //这里依次获取16个默认的保护类型的值 unsignedlongv=pgprot_val(protection_map); //(L_PTE_BUFFERABLE|L_PTE_CACHEABLE)这是linuxpte的定义 //内核中有linux和hardware两种定义方式,为了更好的兼容性 //这里两者间是匹配的,这里将值再加上我们的设置就是 //最新的16个值,将它写回更新 v=(v&~(L_PTE_BUFFERABLE|L_PTE_CACHEABLE))|user_pgprot; protection_map=__pgprot(v); } mem_types[MT_LOW_VECTORS].prot_pte|=kern_pgprot; mem_types[MT_HIGH_VECTORS].prot_pte|=kern_pgprot; mem_types[MT_MINICLEAN].prot_sect&=~PMD_SECT_TEX
(1); pgprot_kernel=__pgprot(L_PTE_PRESENT|L_PTE_YOUNG| L_PTE_DIRTY|L_PTE_WRITE| L_PTE_EXEC|kern_pgprot); mem_types[MT_LOW_VECTORS].prot_l1|=ecc_mask; mem_types[MT_HIGH_VECTORS].prot_l1|=ecc_mask; mem_types[MT_MEMORY].prot_sect|=ecc_mask|cp->pmd; mem_types[MT_ROM].prot_sect|=cp->pmd; switch(cp->pmd){ casePMD_SECT_WT:
mem_types[MT_CACHECLEAN].prot_sect|=PMD_SECT_WT; break; casePMD_SECT_WB:
casePMD_SECT_WBWA:
mem_types[MT_CACHECLEAN].prot_sect|=PMD_SECT_WB; break; } //以上所有的操作都是为了给mem_types这个结构体中的各种类型中的页表参数添加上我们的要求,主要是一级页表,二级页表,ap(访问权限控制);至于domain是利用系统初始化时的值,不用我们再进行干预。
//系统的domain类型一共有四种,kernel——0;user——1;io——2 printk("Memorypolicy:
ECC%sabled,Datacache%s\n", ecc_mask?
"en":
"dis",cp->policy);} bootmem_init(mi);{ unsignedlongaddr,memend_pfn=0; intnode,initrd_node,i; /* *Invalidatethenodenumberforemptyorinvalidmemorybanks */ for(i=0;inr_banks;i++) if(mi->bank.size==0||mi->bank.node>=MAX_NUMNODES) mi->bank.node=-1; //将在4020.cfixup函数中定义的内存信息添加到meminfo结构体中 memcpy(&meminfo,mi,sizeof(meminfo)); //MODULE_START是0xc0000000-16M;以2M为单位,清除内核空间一下的用户空间 for(addr=0;addr//内核在进入保护模式前,还没有启用分页功能,在这之前内核要先建立一个临时内核页表,因为在进入保护模式后,内核继续初始化直到建//立完整的内存映射机制之前,仍然需要用到页表来映射相应的内存地址。
临时页表的初始化是在arch/i386/kernel/head.S中进行的:
//swapper_pg_dir是临时页全局目录表,它是在内核编译过程中静态初始化的.//pg0是第一个页表开始的地方,它也是内核编译过程中静态初始化的.//pmd_off_k是获取虚拟地址为addr的页表项地址//pmd_clear是将()中的页表项地址中的数据清0 pmd_clear(pmd_off_k(addr)); #ifdefCONFIG_XIP_KERNEL /*TheXIPkernelismappedinthemodulearea--skipoverit*/ addr=((unsignedlong)&_etext+PGDIR_SIZE-1)&PGDIR_MASK;#endif //防止xip之后会有变化,检查,做一次用户空间的清除 for(;addr pmd_clear(pmd_off_k(addr)); /* *Clearoutallthekernelspacemappings,exceptforthefirst *memorybank,uptotheendofthevmallocregion. */ //清除内核空间,但是不清楚内存所在区域,也就是 //0xc2000000-0xd0000000的空间 for(addr=__phys_to_virt(mi->bank[0].start+mi->bank[0].size); addr pmd_clear(pmd_off_k(addr)); /* *Locatewhichnodecontainstheramdiskimage,ifany. */ //返回如果有initrd所在的内存节点 initrd_node=check_initrd(mi); /* *Runthrougheachnodeinitialisingthebootmemallocator. */ for_each_node(node){ unsignedlongend_pfn; //为内存建立一级页表(多的话还有二级页表) end_pfn=bootmem_init_node(node,initrd_node,mi); /* *RememberthehighestmemoryPFN. */ if(end_pfn>memend_pfn) memend_pfn=end_pfn; } &n
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Linux arm 启动 c语言部分详解第二讲Start kernel setupa 语言 部分 详解 第二 Start