为了配置内存,首先我们要先熟悉一下ARM的系统控制寄存器。 除了CPU提供的功能外,ARM提供了16个协处理器(Coprocessor)接口, 芯片厂商可以自己外接协处理器来完成更为复杂的功能。
如果想要使用地址映射,那就需要借助MMU(Memory Management Unit)单元对地址进行翻译。 而包含MMU功能在内的诸多系统控制都是要通过Control Coprocessor接口CP15来完成, 这也是ARM预留的几个4个协处理接口之一。
本篇我们主要来看一下ARM访问这些控制寄存器的方式, 并简单看一下我们随后要用到的几个控制寄存器。
Control Register CP15
根据ARM的手册(ARM1176JZ-S TRM)描述:
The processor supports the connection of on-chip coprocessors through an external coprocessor interface. All types of coprocessor instruction are supported.
The ARM instruction set supports the connection of 16 coprocessors, numbered 0-15, to an ARM processor. In the processor, the following coprocessor numbers are reserved:
- CP10 VFP control
- CP11 VFP control
- CP14 Debug and ETM control
- CP15 System control.
You can use CP0-9, CP12, and CP13 for your own external coprocessors.
ARM使用了CP15的接口来实现系统控制的寄存器,
访问这些寄存器需要使用特殊的指令:mrc
和mcr
, 分别对应读和写,
访问一个cp15的寄存器格式类似于:
mrc p15, op1, Rd, CRn, CRm, op2
关于op1, op2, CRn, CRm我们在查相关寄存器的时候看手册就行, Rd是我们使用的通用寄存器。
利用GCC内联汇编的语法,参考一下Linux我们可以写出类似的读写:
1 |
|
其中name就是系统寄存器的名称,比如我们之后要看的System Control Register (SCTLR)
编码就是: #define SCTLR "0, %0, c1, c0, 0"
;
目的就是将系统寄存器的值读到var中,或将val中的值写到系统寄存器里。
SCTLR & TTBR
系统中非常重要的控制寄存器就是SCTLR (在ARMv5中叫Ctrl Register c1), 它负责控制系统的各种重要功能: 中断、FIQ、Cache、Alignment Check、MMU使能等等, 如果我们想要使能MMU的话,就需要将SCTLR的M (bit0)置为1。
TTBR (Translation Table Base Register)顾名思义, 就是存放页表基址的寄存器, 里面存放有页表的物理地址, 当我们打开MMU之后, 每一次访存操作MMU都会把输入地址作为虚拟地址, 从这个寄存器中找到Translation Table, 把地址翻译成物理地址后真正的去访存。
我们可以看一下启动之后这两个寄存器的内容:
1 | void init(pa_t kernel_load_address) |
TTBR0带个0的原因是ARMv7有两个TTBR, ARMv5只有一个, 但是两者的编码是一致的,所以用TTBR0统一起来。 置于为什么有两个TTBR, 等我们以后用到了再说~
小伙伴们可以checkout到我开头给的这个commit, 自己验证一下~ SCTLR的值放到了r5里面, TTBR0放到了r6里面。
1 | # vexpress-a9 (armv7) |
1 | # versatilepb (armv5) |
然后分别对照手册armv7 TRM与arm926ejs_trm查一下两个之间有什么区别。
vexpress-a9上sctlr是 0x00C50078
, versatilepb上是 0x00090078
,
ttbr则都是0。
那么接下来我们就要认真研究一下TTBR的格式,来构建我们的页表啦。
Note
aarch64上系统寄存器已经不是用cp15访问了,以后我们开始支持aarch64的时候再说~