linux-kernel - 为什么要读取__turn_mmu_on中的id寄存器?

标签 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中被覆盖?

最佳答案

对齐可能不是必需的,但可能用于确保整个函数适合缓存行,因此最后几条指令将从缓存中执行,而不必从内存中获取(即使函数应该保持在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 :

...
We can however get closer to the Xscale recommended sequence by knowing how things work on other CPUs, and knowing what we're doing here. If we insert the following instruction after the mcr, then this should solve your issue.

mrc p15, 0, r0, c1, c0

Since the read-back of the same register is guaranteed by the ARM architecture manual to return the value that was written there (if it doesn't, the CPU isn't an ARM compliant implementation), this means we can guarantee that the write to the register has taken effect. The use of the "mov r0, r0" instructions are the same as in the CPWAIT macro. The mov pc, lr is equivalent to the "sub pc, pc, #4" (they are defined to be the same class of instructions), so merely adding one instruction should guarantee that the Xscale works as expected.
...

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

关于linux-kernel - 为什么要读取__turn_mmu_on中的id寄存器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17835806/

相关文章:

c - Linux内核中嵌入锁的动态分配/释放结构

动态使用不同定义的 C 宏

c - 内部写入at91sam7s256 flash

linux - 在Linux内核模块中实现民意测验

android - 如何在X86 linux中调用android动态库(.so)?

arm - 我可以使用什么来调试/跟踪 Pandaboard 上的逐步 Freebsd 内核启动过程?

assembly - ARM - 如何将汇编代码转换为机器语言

c - 如何使用内核头文件编译用户空间程序

linux - 与虚拟内存相比,为什么我的进程占用更高的驻留内存?

c - disable_local_irq 和内核定时器