Android 从内核模块中查找异常向量表的物理地址

Android 从内核模块中查找异常向量表的物理地址,android,memory-management,linux-kernel,arm,Android,Memory Management,Linux Kernel,Arm,我有一个android设备-三星galaxy s2,内核版本为2.6.35.14(arm cortex a9) 我试图找到异常向量表的物理地址。我知道它位于0xffff0000虚拟地址。(我可以通过内核模块打印它的值) 我还知道,大多数内核虚拟地址(到物理地址)的转换是由值为0x8000000的子站完成的 我有一个可以直接从设备内存读取数据的设备,我想得到异常向量表 当我构建内核模块并尝试使用宏virt_to_phys(0xffff0000)时,我得到了一些地址,但表不在那里。我用这种方法成功地

我有一个android设备-三星galaxy s2,内核版本为2.6.35.14(arm cortex a9)

我试图找到异常向量表的物理地址。我知道它位于0xffff0000虚拟地址。(我可以通过内核模块打印它的值)

我还知道,大多数内核虚拟地址(到物理地址)的转换是由值为0x8000000的子站完成的

我有一个可以直接从设备内存读取数据的设备,我想得到异常向量表

当我构建内核模块并尝试使用宏virt_to_phys(0xffff0000)时,我得到了一些地址,但表不在那里。我用这种方法成功地找到了系统调用表,但这里宏给了我错误的地址

有人知道为什么会这样吗?异常向量表的地址是否驻留在特殊的物理地址中?内核是否以某种特殊方式转换其地址

谢谢

异常向量表在Linux中保持相当稳定,从2.6.35到最新的主线。它是在启动阶段的早期分配的,涉及到memblock启动分配器。所涉及的文件是、和(链接器脚本),位于内核目录中,以及mm(或内存管理ARM目录)中。此外,向量表必须始终映射,并且用户进程可以读取它。这是由用户使用的;助手例程也映射到此页面

解释 从vmlinux.lds.S

向量和存根是可重定位的代码,唯一重要的是它们的相对偏移量

\uuuu vectors\u start
表示向量页面中的代码,可在条目armv.S中找到。但是,该函数在traps.c中重新定位。引导分配器为虚拟0xffff000地址保留一页(如果配置了高向量)。在2.6.35内核中,memblock分配器用于。这里
devicemaps\u init()
通过调用
early\u alloc()
来分配页面。此页面不遵循正常的内核地址空间规则,
virt\u to\u phys
可能不会被使用,因为虚拟地址是强制的

但是,内核地址确实存在于原始
memblock\u alloc()
返回地址中。这是
devicemaps_init()
中的指针
向量
;此地址与
virt\u to\u phys
phys\u to\u virt
一起使用

可以很容易地找到条目armv.S中的
\u向量\u start
等的物理地址,并计算出物理地址;但是,它在初始化阶段结束时被丢弃,我认为您对此不感兴趣

答复
您可以调用,
memblock\u dump\u all(void)
,查看
dmesg
,并使用这些指针尝试定位
向量
页面。它将是4k大小。您可以更改
设备映射_init()
以导出
向量
值。使用未修改内核的唯一方法是遍历ARMmmu表;这是另一种情况。

也可以直接使用MMU(寄存器ATS1Cxx和PAR)执行V=>p转换。有关血淋淋的详细信息,请参见第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);
这些常数是正确的

  • 0xffff0000是高向量虚拟地址
  • 0xfffff000是4k页面的掩码

这仅适用于较新系列的ARM处理器,如Cortex系列。

也就是说
devicemaps_init
中的
向量
指针是0xffff0000的虚拟别名,映射到同一物理页面。别名的原因应该是显而易见的。大多数ARM CPU需要向量为0或0xffff0000,尽管较新的ARMs可能会放弃这一点。谢谢您的快速回答!。让我看看我是否理解正确。memblock_alloc()返回指向向量表(变量-向量)的虚拟地址。此外,内核必须将地址0xffff0000映射到先前分配的物理地址。因此,内核中有两个虚拟地址映射到相同的物理地址,或者在0xffff0000映射之后,第一个虚拟地址不相关?
memblock\u alloc()
分配一个正常的物理/虚拟对。然后在
devicemaps_init()
中,为0xffff0000创建第二个别名。第一虚拟地址是相关的并且保持活动状态;它是
devicemaps_init()
向量
指针的值。它保留在MMU表中;MMU表是从virt到PHY的列表;所以两个条目指向同一物理页面。0xffff0000不符合您观察到的正常规则。此别名的一个重要警告。如果要修改其中一个(而不是0xffff0000),则需要刷新缓存和写入缓冲区,或者旧值可能会保留一段时间(在缓存中的0xffff0000值中)。缓存生成同一数据的第二个副本,它不知道别名。