build_mem_type_table函数主要是mem_types对不同entry映射条目的后面域内容进行定义。 prepare_page_table是将虚拟地址对应的可以清空的字段全部清空。
1. build_mem_type_table
/*
* Adjust the PMD section entries according to the CPU in use.
*/
static void __init build_mem_type_table(void)
{
struct cachepolicy *cp;
unsigned int cr = get_cr();
unsigned int user_pgprot, kern_pgprot;
int cpu_arch = cpu_architecture();
int i;
#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
printk("cpu_arch: %d\n", cpu_arch);
if (cpu_arch < CPU_ARCH_ARMv5) {
if (cachepolicy >= CPOLICY_WRITEALLOC)
cachepolicy = CPOLICY_WRITEBACK;
ecc_mask = 0;
}
/*
* ARMv5 and lower, bit 4 must be set for page tables.
* (was: cache "update-able on write" bit on ARM610)
* However, Xscale cores require this bit to be cleared.
*/
if (cpu_is_xscale()) {
for (i = 0; i < ARRAY_SIZE(mem_types); i++) {
mem_types[i].prot_sect &= ~PMD_BIT4;
mem_types[i].prot_l1 &= ~PMD_BIT4;
}
} else if (cpu_arch < CPU_ARCH_ARMv6) {
for (i = 0; i < ARRAY_SIZE(mem_types); i++) {
if (mem_types[i].prot_l1)
mem_types[i].prot_l1 |= PMD_BIT4;
if (mem_types[i].prot_sect)
mem_types[i].prot_sect |= PMD_BIT4;
}
}
cp = &cache_policies[cachepolicy];
kern_pgprot = user_pgprot = cp->pte;
printk("kern_pgprot: %u", kern_pgprot);
/*
* Enable CPU-specific coherency if supported.
* (Only available on XSC3 at the moment.)
*/
if (arch_is_coherent()) {
if (cpu_is_xsc3()) {
mem_types[MT_MEMORY].prot_sect |= PMD_SECT_S;
mem_types[MT_MEMORY].prot_pte |= L_PTE_SHARED;
}
}
/*
* ARMv6 and above have extended page tables.
*/
if (cpu_arch >= CPU_ARCH_ARMv6 && (cr & CR_XP)) {
/*
* Mark cache clean areas and XIP ROM read only
* from SVC mode and no access from userspace.
*/
mem_types[MT_ROM].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE;
mem_types[MT_MINICLEAN].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE;
mem_types[MT_CACHECLEAN].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE;
/*
* Mark the device area as "shared device"
*/
mem_types[MT_DEVICE].prot_pte |= L_PTE_BUFFERABLE;
mem_types[MT_DEVICE].prot_sect |= PMD_SECT_BUFFERED;
#ifdef CONFIG_SMP
/*
* Mark memory with the "shared" attribute for SMP systems
*/
user_pgprot |= L_PTE_SHARED;
kern_pgprot |= L_PTE_SHARED;
mem_types[MT_MEMORY].prot_sect |= PMD_SECT_S;
#endif
}
for (i = 0; i < 16; i++) {
unsigned long v = pgprot_val(protection_map[i]);
v = (v & ~(L_PTE_BUFFERABLE|L_PTE_CACHEABLE)) | user_pgprot;
protection_map[i] = __pgprot(v);
}
mem_types[MT_LOW_VECTORS].prot_pte |= kern_pgprot;
mem_types[MT_HIGH_VECTORS].prot_pte |= kern_pgprot;
if (cpu_arch >= CPU_ARCH_ARMv5) {
#ifndef CONFIG_SMP
/*
* Only use write-through for non-SMP systems
*/
mem_types[MT_LOW_VECTORS].prot_pte &= ~L_PTE_BUFFERABLE;
mem_types[MT_HIGH_VECTORS].prot_pte &= ~L_PTE_BUFFERABLE;
#endif
} else {
mem_types[MT_MINICLEAN].prot_sect &= ~PMD_SECT_TEX(1);
}
pgprot_user = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | user_pgprot);
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;
}
printk("Memory policy: ECC %sabled, Data cache %s\n",
ecc_mask ? "en" : "dis", cp->policy);
for (i = 0; i < ARRAY_SIZE(mem_types); i++) {
struct mem_type *t = &mem_types[i];
if (t->prot_l1)
t->prot_l1 |= PMD_DOMAIN(t->domain);
if (t->prot_sect)
t->prot_sect |= PMD_DOMAIN(t->domain);
printk("mem_types %d: prot_pte=0x%x, prot_pte_ext=0x%x, prot_l1=0x%x, prot_sect=0x%x, domain=0x%x\n", i, t->prot_pte, t->prot_pte_ext, t->prot_l1, t->prot_sect, t->domain);
}
}
代码执行打印结果如下:
cpu_arch: 3
kern_pgprot: 12Memory policy: ECC disabled, Data cache writeback
mem_types 0: prot_pte=0xa3, prot_pte_ext=0x0, prot_l1=0x51, prot_sect=0x452, domain=0x2
mem_types 1: prot_pte=0xa3, prot_pte_ext=0x80, prot_l1=0x51, prot_sect=0x2452, domain=0x2
mem_types 2: prot_pte=0xaf, prot_pte_ext=0x0, prot_l1=0x51, prot_sect=0x45e, domain=0x2
mem_types 3: prot_pte=0xa3, prot_pte_ext=0x0, prot_l1=0x51, prot_sect=0x1456, domain=0x2
mem_types 4: prot_pte=0x0, prot_pte_ext=0x0, prot_l1=0x0, prot_sect=0x1e, domain=0x0
mem_types 5: prot_pte=0x0, prot_pte_ext=0x0, prot_l1=0x0, prot_sect=0x1a, domain=0x0
mem_types 6: prot_pte=0xcf, prot_pte_ext=0x0, prot_l1=0x31, prot_sect=0x0, domain=0x1
mem_types 7: prot_pte=0xdf, prot_pte_ext=0x0, prot_l1=0x31, prot_sect=0x0, domain=0x1
mem_types 8: prot_pte=0x0, prot_pte_ext=0x0, prot_l1=0x0, prot_sect=0x41e, domain=0x0
mem_types 9: prot_pte=0x0, prot_pte_ext=0x0, prot_l1=0x0, prot_sect=0x1e, domain=0x0
2. prepare_page_table
prepare_page_table: start=0x0, MODULE_START=0xbf000000, PAGE_OFF=0xc0000000, PGDIR_SIZE=0x200000, VMALLOC_END=0xe0000000, exc_memory_bank=0xc4000000
主要是这些字段进行清空