您的位置:首页 > 运维架构 > Linux

linux内核地址有效性判断方法

2014-11-30 16:23 155 查看
如果只是需要大致地判断范围,可以参考内核\linux-3.4.104\Documentation\x86\x86_64\mm.txt中的对各个段的分配的描述。但是如果需要更加精确地判断,就需要根据内核页表,一级一级地查找,查看是否存在对应的物理地址(内核态的地址不存在SWAP的问题),下面是内核代码段(针对X86-64,有修改)
int kern_addr_valid(unsigned long address)
{
pgd_t *pgd;
pud_t *pud;
pmd_t *pmd;
pte_t *pte;
unsigned long high_bits = ((long)address) >> 47;

if (high_bits != 0 && high_bits != -1UL)
return 0;/*原因见INTEL相关文档*/
/*swapper_pg_dir对应的符号init_level4_pgt在有的版本没有导出
需要用kallsyms_lookup_name获取到该符号的地址*/
pgd = swapper_pg_dir + pgd_index(address);
if (pgd_present(*pgd))
return 0;
pud = pud_offset(pgd, address);
if (pud_present(*pud))
return 0;
if (pud_large(*pud))
return pfn_valid(pud_pfn(*pud));
pmd = pmd_offset(pud, address);
if (pmd_present(*pmd))
return 0;
if (pmd_large(*pmd))
return pfn_valid(pmd_pfn(*pmd));
pte = pte_offset_kernel(pmd, address);
if (pte_present(*pte))
return 0;
return pfn_valid(pte_pfn(*pte));
}
以上代码段基本上和内核的中有关于对high_bits的做法,是基于X86-64架构对64位线性地址的处理,当前的架构采用9-9-9-9-12的模式,只是用了48位,就规定:高16bits(48-63)必须和第47bits保持一致。详细的说明参见《Intel® 64 and IA-32 Architectures Software Developer’s Manual Volume 1:Basic Architecture》3.3.7.1  Canonical Addressing:
Intel 64 architecture defines a 64-bit linear address. Implementations can support less. The first implementation
of IA-32 processors with Intel 64 architecture supportsa 48-bit linear address. This means a canonical address
must have bits 63 through 48 set to zeros or ones (depending on whether bit 47 is a zero or one).
如果违反该规则,CPU会检查到该错误并发起一个General protection fault
注意:以上的代码,是判断一个地址是否可以读,当然只是保证读的话不产生page fault,可以和magic值一起进一步确认。如果要判断是否可写,需要进一步检查

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: