为什么要在__turn_mmu_on中读取id寄存器?

时间:2013-07-24 13:42:59

标签: linux-kernel arm

在阅读了有关ARM linux内核启动过程的代码几天之后,除了函数__turn_mmu_on:中的几个棘手部分之外,我理解了其中的大多数部分

        .align  5
   __turn_mmu_on:
      mov   r0, r0
      mcr   p15, 0, r0, c1, c0, 0       @ write control reg
      mrc   p15, 0, r3, c0, c0, 0       @ read id reg
      mov   r3, r3
      mov   r3, r3
      mov   pc, r13
   ENDPROC(__turn_mmu_on)

最后一条指令mov pc, r13将转移到__mmap_switched,如下所示:

    __mmap_switched:
        adr r3, __switch_data + 4
        ....
  • 为什么有必要将它对齐为32字节(缓存行的大小)边界?
  • 读取ID寄存器的值(其值甚至未使用)的目的是什么,因为只需在指令r3中覆盖寄存器adr r3, __switch_data + 4

1 个答案:

答案 0 :(得分:3)

对齐可能不是必需的,但可能用于确保整个函数适合缓存行,因此最后几条指令将从缓存中执行,而不必是从内存中取出(即使函数 仍然在MMU上的同一地址,因为它的身份映射)。

要追踪MRC指令的来源并不容易,但我认为我是found it

Date: 2004-04-04 04:35 +200
To: linux-arm-patches
Subject: [Linux-arm-patches] 1204.1: XSCALE processor stalls when enabling MMU
--- kernel-source-2.5.21-rmk/arch/arm/kernel/head.S    Sun Jun  9 07:26:29 2002
+++ kernel-2.5.21-was/arch/arm/kernel/head.S    Fri Jul 12 20:41:42 2002
@@ -118,9 +118,7 @@ __turn_mmu_on:
     orr    r0, r0, #2            @ ...........A.
 #endif
     mcr    p15, 0, r0, c1, c0
-    mov    r0, r0
-    mov    r0, r0
-    mov    r0, r0
+    cpwait    r10
     mov    pc, lr
[...]
+/*
+ * cpwait - wait for coprocessor operation to finish
+ * this is the canonical way to wait for cp updates
+ * on PXA2x0 as proposed by Intel
+ */
+    .macro    cpwait reg
+    mrc    p15, 0, \reg, c2, c0, 0    @ arbitrary cp reg read
+    mov    r0, r0                    @ nop
+    sub    pc, pc, #4                @ nop
+    .endm

随后讨论这个补丁的优点ended in the current approach

  

...
  然而,我们可以更接近Xscale推荐的序列   知道事情如何在其他CPU上工作,并知道我们正在做什么   这里。如果我们在mcr之后插入以下指令,那么这个   应该解决你的问题。

mrc p15, 0, r0, c1, c0
     

由于ARM对保证同一寄存器的回读   体系结构手册返回那里写的值(如果它   不是,CPU不是ARM兼容的实现),这意味着我们   可以保证对寄存器的写入生效。使用   “mov r0,r0”指令的含义与CPWAIT宏中的相同。   mov pc,lr相当于“sub pc,pc,#4”(它们是定义的   是指令的 class ,所以只添加一个   指示应保证Xscale按预期工作   ...

最初的补丁来自Lothar Wassmann,最终的代码可能是Russel King。