我有一个Android设备 - 三星galaxy s2内核版本2.6.35.14(arm cortex a9)
我试图找到异常向量表的物理地址。我知道它在0xffff0000虚拟地址。 (我可以通过内核模块打印它的值)
我也知道大多数内核虚拟地址(到物理)的转换是由值0x8000000的变电站完成的。
我有一个可以直接从设备内存中读取数据的设备,我希望得到异常向量表。
当我构建一个内核模块并尝试使用宏virt_to_phys(0xffff0000)时,我有一些地址,但表不存在。我成功地找到了系统调用表,但这里的宏给了我错误的地址。
有谁知道为什么会这样?异常向量表的地址是否位于特殊的物理地址中?内核是否以某种特殊方式翻译其地址?
谢谢!!答案 0 :(得分:5)
异常向量表在Linux中保持相当稳定,从2.6.35到最新的主线。它在引导阶段很早就分配,并涉及 memblock 引导分配器。所涉及的文件是内核目录中的entry-armv.S,traps.c和vmlinux.lds.S(链接描述文件),其中init.c和mmu.c位于 mm < / strong>(或内存管理 ARM 目录)。此外,向量表必须始终映射,并且可由用户进程读取。这由kernel user helpers使用;辅助例程也映射到此页面。
来自 vmlinux.lds.S ,
向量和存根是可重定位的代码,唯一重要的是它们的相对偏移
__vectors_start
代表矢量页面中的代码,可在 entry-armv.S 中找到。但是,该函数在 traps.c 中重定位。 引导分配器为虚拟0xffff000地址保留页面(如果配置了高向量)。在2.6.35内核中, memblock 分配器用于init.c。此处mmu.c's devicemaps_init()
通过调用early_alloc()
来分配页面。此页面不遵循正常的内核地址空间规则,并且可能不会使用virt_to_phys
,因为强制虚拟地址。
但是,内核地址确实存在原始memblock_alloc()
返回地址。这是vector
中的指针devicemaps_init()
;此地址适用于virt_to_phys
和phys_to_virt
。
可以轻松找到 entry-armv.S 中的__vectors_start
等物理地址并计算物理地址;但是,它会在 init 阶段结束时被丢弃,我认为你对此并不感兴趣。
您可以致电memblock_dump_all(void)
并查看dmesg
并使用这些指针尝试找到vector
页面。它将是4k大小。您可以更改devicemaps_init()
以导出vector
值。使用未修改内核的唯一方法是使用 ARM mmu表;那是另一个故事。
答案 1 :(得分:2)
也可以直接使用MMU(寄存器ATS1Cxx和PAR)来执行V =&gt; P转换。有关详细信息,请参阅ARM ARM的B4.2.4节。
如果以这种方式使用MMU寄存器,则可能需要使用寄存器的其他用途来防止竞争。
可以使用以下代码从任何内核驱动程序访问它,
unsigned int pa;
asm("\t mcr p15, 0, %0, c7, c8, 2\n"
"\t isb\n"
"\t mrc p15, 0, %0, c7, c4, 0\n" : "=r" (pa) : "0" (0xffff0000));
printk("Vector is %x\n", pa & 0xfffff000);
常数是正确的。
这仅适用于后来的系列ARM处理器,例如 Cortex 系列。