Arm64 Linux 4.19内核空间地址PTE查找问题求助
我正在为研究开发一款Linux 4.19(ArmV8)内核模块,需要查找内核空间地址的PTE。以下是根据建议优化后的代码(使用READ_ONCE优化页表项读取,并调整了变量命名):
pte_t *lookup_address_arm64(unsigned long addr, unsigned int *level) { pgd_t *pgdp; pud_t *pudp, pud; pmd_t *pmdp, pmd; *level = 0; pgd_t *pgd_base; unsigned long phys_addr; // 读取TTBR1_EL1获取PGD,尝试过pgd_offset_k但init_mm未定义 phys_addr = read_sysreg(ttbr1_el1) & ((1UL << 48) - 2); // 获取基地址 // 转换为虚拟地址 pgd_base = (pgd_t *)phys_to_virt(phys_addr); pgdp = pgd_offset_raw(pgd_base, addr); if (pgd_none(READ_ONCE(*pgdp))) return NULL; pudp = pud_offset(pgdp, addr); pud = READ_ONCE(*pudp); if (pud_none(pud)) return NULL; *level = 3; if (pud_sect(pud)) return (pte_t *)pudp; pmdp = pmd_offset(pudp, addr); pmd = READ_ONCE(*pmdp); if (pmd_none(pmd)) return NULL; *level = 2; if (pmd_sect(pmd)) return (pte_t *)pmdp; *level = 1; return pte_offset_kernel(pmdp, addr); }
当前代码未触发内核panic,但会在return (pte_t *)pudp;处返回。我要查找的地址位于物理内存直接映射区域,代码返回是因为检测到pud为大页PTE,但我已经通过在.config中取消设置CONFIG_TRANSPARENT_HUGEPAGE_ALWAYS禁用了大页,且通过以下命令验证:
# cat /proc/meminfo | grep -i huge
HugePages_Total: 0 HugePages_Free: 0 HugePages_Rsvd: 0 HugePages_Surp: 0 Hugepagesize: 2048 kB Hugetlb: 0 kB
调试时打印的关键变量值:
[ 15.990883] [look_up_addr] addr at 0xffff800040000000 pgd_base at 0xffff8000017f8000 [ 15.993070] [look_up_addr] addr at 0xffff800040000000 pgdp at 0xffff8000017f8800 [ 15.993835] [look_up_addr] addr at 0xffff800040000000 pgd val = 0xbdff7803 [ 15.994384] [look_up_addr] addr at 0xffff800040000000 pudp at 0xffff80007dff7008 [ 15.994812] [look_up_addr] addr at 0xffff800040000000 pud val = 0xe8000080000f11
此前已解决的内核panic信息:
[ 20.339178] Unable to handle kernel paging request at virtual address ffffc17f40000800
[ 20.342033] Mem abort info:
[ 20.342592] ESR = 0x96000004
[ 20.343163] Exception class = DABT (current EL), IL = 32 bits
[ 20.344075] SET = 0, FnV = 0
[ 20.346614] EA = 0, S1PTW = 0
[ 20.347305] Data abort info:
[ 20.347707] ISV = 0, ISS = 0x00000004
[ 20.348805] CM = 0, WnR = 0
[ 20.353096] swapper pgtable: 4k pages, 48-bit VAs, pgdp = 00000000a2e904bd
[ 20.354361] [ffffc17f40000800] pgd=0000000000000000
[ 20.355638] Internal error: Oops: 96000004 [#1] PREEMPT SMP
[ 20.357312] Dumping ftrace buffer:
[ 20.358719] (ftrace buffer empty)
内容的提问来源于stack exchange,提问作者JamesMcgill

