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

时间:2013-10-09 15:03:45

标签: android memory-management linux-kernel arm

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

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

我也知道大多数内核虚拟地址(到物理)的转换是由值0x8000000的变电站完成的。

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

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

有谁知道为什么会这样?异常向量表的地址是否位于特殊的物理地址中?内核是否以某种特殊方式翻译其地址?

谢谢!!

2 个答案:

答案 0 :(得分:5)

异常向量表在Linux中保持相当稳定,从2.6.35到最新的主线。它在引导阶段很早就分配,并涉及 memblock 引导分配器。所涉及的文件是内核目录中的entry-armv.Straps.cvmlinux.lds.S(链接描述文件),其中init.cmmu.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_physphys_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);

常数是正确的。

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

这仅适用于后来的系列ARM处理器,例如 Cortex 系列。