[原创]Linux arm 启动 c语言部分详解第二讲(Start kernel-> setup_a
?? ??
??Written by leeming ??
??这一讲是主要讲setup_arch中那个没有解释的函数解释完毕,完成setup_arch的函数,好让我们的start_kernel继续下去。 ?? ??/* ??
?? * paging_init() sets up the page tables, initialises the zone memory ??
?? * maps, and sets up the zero page, bad page and bad page tables. ??
?? *这部分的主要工作建立页表,初始化内存。 ?? ??*/ ??
??void __init paging_init(struct meminfo *mi, struct machine_desc *mdesc) ?? ??{ ??
?? void *zero_page; ??
??//这个函数主要是用来建立各种类型的页表选项(比如内存是MEMORY类型,设备室DEVICE,中断向量表是HIGH_VECTORS) ??
?? build_mem_type_table(); ?? ??{ ??
?? struct cachepolicy *cp; ??
?? //获取cp15处理器的c1寄存器位 ??
?? unsigned int cr = get_cr(); ??
?? unsigned int user_pgprot, kern_pgprot; ??
?? //获取处理器架构版本 ??
?? int cpu_arch = cpu_architecture(); ??
?? int i; ?? ?? ??
?? //根据处理器版本号调整cache政策,不是写缓冲区的政策 ??
??#if defined(CONFIG_CPU_DCACHE_DISABLE) ??
?? if (cachepolicy > CPOLICY_BUFFERED) ??
?? cachepolicy = CPOLICY_BUFFERED; ??
??#elif defined(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_l1 prot_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_pgprot user_pgprot是内核和用户空间的二级页表描述符 ??
?? kern_pgprot = user_pgprot = cp->pte;
?? ?? ??
?? //以下删除了非v4t架构的高版本代码 ?? ?? ??
?? for (i = 0; i ??
?? //这里依次获取16个默认的保护类型的值 ??
?? unsigned long v = pgprot_val(protection_map); ??
?? //(L_PTE_BUFFERABLE|L_PTE_CACHEABLE)这是linux pte的定义 ??
?? //内核中有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) { ??
?? case PMD_SECT_WT: ??
?? mem_types[MT_CACHECLEAN].prot_sect |= PMD_SECT_WT; ??
?? break; ??
?? case PMD_SECT_WB: ??
?? case PMD_SECT_WBWA: ??
?? mem_types[MT_CACHECLEAN].prot_sect |= PMD_SECT_WB; ??
?? break; ??
?? }