static int pt_walk_init( void )
{
unsigned long virt;
pgd_t *pgd_base;
pgd_t *pgd;
uint32_t pgd_valx;
unsigned long va;
unsigned long pfn_base;
unsigned long pa;
phys_addr_t calc_pa, real_pa;
unsigned long val1,val2,val3;
unsigned int *pgd_one;
// 分配内核线性映射地址
virt = (unsigned long)__get_free_page(GFP_KERNEL);
if (!virt) {
pr_err("alloc page failed\n");
return -ENOMEM;
}
va = virt;
//写入 VA
*(volatile unsigned long *)va = 0x12345678; //先访问一次,触发缺页,填充真实页表
//pr_info("va = %08lx\n", va);
//然后用 MMU 算出的物理地址读
calc_pa = (unsigned long)virt_to_phys((void *)va);
//pr_info("calc_pa = %08lx\n", calc_pa);
val1 = *(volatile unsigned long *)phys_to_virt(calc_pa);
//pr_info("val1 = %08lx\n", val1);
//pr_info("phys_to_virt(calc_pa) = %08lx\n", phys_to_virt(calc_pa) );
//PAGE_OFFSET = 0x80000000
//PHYS_OFFSET = 0x68000000
pr_info("[第一步] 打印内核内存布局真相\n");
pr_info("虚拟地址 VA = 0x%08lx\n", va);
pr_info("真实物理地址 PA virt_to_phys = 0x%08lx\n", (unsigned long)virt_to_phys((void *)va));
pr_info("VA - PAGE_OFFSET = 0x%08lx\n", va - PAGE_OFFSET);
pr_info("VA - virt_to_phys = 0x%08lx\n", va - (unsigned long)virt_to_phys((void *)va));
//步骤1:打印虚拟地址拆分(硬件行为)
pr_info("[步骤1] 虚拟地址硬件拆分 (VA = 索引 + 偏移)\n");
unsigned int idx = (va >> 20) & 0xFFF; // 高12位 → PGD索引
unsigned int off = va & 0xFFFFF; // 低20位 → 偏移
pr_info("VA [31:20] 索引 = 0x%03x\n", idx);
pr_info("VA [19:0] 偏移 = 0x%05x\n", off);
// =========================================================================
// 步骤2:计算PGD地址并读取PGD原值
// =========================================================================
pr_info("\n=======================================================\n");
pr_info("[步骤2] 读取 PGD 原始值\n");
pr_info("=======================================================\n");
pgd_base = init_mm.pgd;
pgd = pgd_offset(&init_mm, va);
pgd_valx = pgd_val(*pgd);
pr_info("PGD 基地址 = 0x%08x\n", (unsigned int)pgd_base);
pr_info("PGD 计算地址 = 0x%08x\n", (unsigned int)pgd);
pr_info("PGD 原始值 = 0x%08x\n", pgd_valx);
pgd_one = pgd;
if( (virt>>20) & 1 ){
pgd_one++;
pgd_valx = pgd_one[0];
pr_info("PGD 修正值 = 0x%08x\n", pgd_valx);
}
// HEXDUMP PGD 内存
pr_info("PGD 内存 hexdump:\n");
print_hex_dump(KERN_INFO, "PGD: ", DUMP_PREFIX_ADDRESS, 16, 4,
pgd_base+pgd_index(va), 0x40, false);
//步骤3:解析 PGD 位格式(ARM Section 格式)
pr_info("[步骤3] 解析 PGD 硬件格式 (Section 1MB)\n");
int type = pgd_valx & 3;
pr_info("Bit[1:0] 类型 = %d (10=Section 1MB大页)\n", type);
if (type == 2) {
pr_info("确认:这是 ARM 1MB Section 映射\n");
}
pr_info("Bit[4:2] AP = %d\n", (pgd_valx >> 2) & 7);
pr_info("Bit[5] CB = %d\n", (pgd_valx >> 5) & 1);
pr_info( "Bit[31:12] 基地址 = 0x%08x\n", (unsigned int)(pgd_valx & 0xFFF00000) );
//步骤4:硬件计算最终物理地址
pr_info("[步骤4] 硬件计算最终物理地址\n");
pfn_base = (pgd_valx & 0xFFF00000);
pa = pfn_base | (va & 0x000FFFFF);
pr_info("PA = PGD[31:12] + VA[19:0]\n");
pr_info("PA = 0x%08lx + 0x%05x = 0x%08lx\n", pfn_base, off, pa);
// =========================================================================
// 总结
// =========================================================================
pr_info("\n=======================================================\n");
pr_info( "[硬件流程完成]\n" );
pr_info("VA = 0x%08lx --> PA = 0x%08lx\n", va, pa);
//free_page(virt);
return 0;
}

296

被折叠的 条评论
为什么被折叠?



