Linux中针对ARM架构的向量页映射

3
我正试图理解向量页是如何映射到0xffff0000的。我参考了3.14内核。
根据early_trap_init()traps.c中的注释,向量从 entry-armv.S复制到向量页。
似乎是从devicemaps_init() mmu.c中调用了early_trap_init()
在调用early_trap_init()之前,它使用early_alloc()创建向量页,并且我没有看到任何映射。
请帮忙理解向量页是如何映射的?
1个回答

3
答案在你的devicemaps_init()链接中(约在3.14版本的第1250行)。
     /*
      * Create a mapping for the machine vectors at the high-vectors
      * location (0xffff0000).  If we aren't using high-vectors, also
      * create a mapping at the low-vectors virtual address.
      */
     map.pfn = __phys_to_pfn(virt_to_phys(vectors));
     map.virtual = 0xffff0000;
     map.length = PAGE_SIZE;
 #ifdef CONFIG_KUSER_HELPERS
     map.type = MT_HIGH_VECTORS;
 #else
     map.type = MT_LOW_VECTORS;
 #endif
     create_mapping(&map);

这里还有其他代码来进行更多的映射。请注意,除了物理向量指令外,还有用于切换模式的代码。这是通过vector_stub汇编宏完成的。注释中的解释非常好(也可以参见第二个相关链接)。

  向量存根。
将此代码复制到0xffff1000,以便我们可以在向量中使用分支而不是ldr。请注意,此代码不得超过页面大小。
公共存根入口宏: 进入IRQ模式,spsr = SVC / USR CPSR,lr = SVC / USR PC
SP指向最少量的处理器专用内存,其地址被复制到r0以供特定于模式的异常处理程序使用。

所以我们可以在向量中使用分支意味着向量表中的第一条指令。

相关:查找异常向量表的物理地址
               Linux内核ARM异常堆栈初始化


我原本以为“首先会为向量页(使用物理地址)创建内存,并将其映射到虚拟地址0xffff0000,然后将向量复制到向量页中”,但在看到回复后,发现首先使用early_alloc()为向量页创建了内存(它返回虚拟地址),通过调用early_trap_init()复制向量,之后才对向量页进行了0xffff0000的映射。我的疑问是,向量页是否有两个虚拟映射?(第一个虚拟地址是由early_alloc()返回的,第二个虚拟映射如上所述)。 - user3693586
是的,有多个映射。这没问题吗?有些是读/写的,而其他一些是只读的。有些可以被用户空间访问,而其他一些则不能。我正在试图理解如何将向量页映射到0xffff0000是我回答过的一个问题。你从来没有提到过关于两个映射的疑问 - artless noise
起初我对向量页映射有疑问,看到回复后,我又对向量页的两个虚拟映射产生了疑问。 - user3693586
“我有疑问”在印度和一些浪漫语言(西班牙语、意大利语等)中很常见。根据该页面,“我有一个问题”是更好的翻译/表达方式。对于许多以英语为母语的人来说,“我有疑问”意味着你不相信对方所说的话,因此这并没有激励我回答第二个问题。“我的问题是,对于向量页,是否发生了两个虚拟映射?”我简要地评论了一下。我已经有很多提问者在后续询问中使用了这个“疑问”表达方式。 - artless noise

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接