Linux arm 启动 c语言部分详解第二讲Start kernel-- setup - a 下载本文

内容发布更新时间 : 2024/9/20 15:40:22星期一 下面是文章的全部内容请认真阅读。

[原创]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; ??

??       }