2

经过几天阅读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
4

1 回答 1

3

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

追踪MRC指令的来源并不容易,但我找到了

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

随后关于此补丁优点的讨论以当前方法结束

...
但是,我们可以通过了解其他 CPU 上的工作方式以及了解我们在这里所做的工作来更接近 Xscale 推荐的序列。如果我们在 mcr 之后插入以下指令,那么这应该可以解决您的问题。

mrc p15, 0, r0, c1, c0

由于 ARM 体系结构手册保证对同一寄存器的回读返回写入那里的值(如果没有,则 CPU 不是 ARM 兼容的实现),这意味着我们可以保证写入登记册已生效。“mov r0, r0”指令的使用与 CPWAIT 宏中的相同。mov pc, lr 等价于“sub pc, pc, #4”(它们被定义为同一指令),因此只需添加一条指令即可保证 Xscale 按预期工作。
...

原始补丁来自 Lothar Wassmann,最终代码可能来自 Russel King。

于 2013-07-24T14:54:58.637 回答