rpi_start.Sを読む (第10回)
いよいよ10回目に入りました。
今回読むのは次の部分です。
理論上、MMUはオフなので、これから行う操作がすべて必要ではないけれど、この辺でやるしかないので、TTB(Translation Table Base)をセットする典型的な手順を実行します、って感じですかねぇ。
まぁ、先に進みましょうか。
movでレジスタr0をゼロにしてInvalidate_I_cache(reg)を実行します。
Invalidate_I_cache(reg)はずいぶん最初のほうに記述がありました。
ちなみに、I cacheはInstruction cacheでD cacheはData cacheです。
c7はキャッシュ操作のレジスタです。ARM1176JZ-S™ Technical Reference Manualに、「MCR p15, 0,, c7, c5, 0 Invalidate entire Instruction Cache」とあります。
なんでかわかりませんが、4回ほど連発してますね。
このあたりから、マニュアルと首っ引きで調べる感じです。
それでは、202行目に戻りましょう。
, c7, c14, 0 SBZ Clean and Invalidate Entire Data Cache.」とあります。
さっきがインストラクションキャッシュだったので、今度はデータキャッシュですね。
進めましょう。
Lctl_ID_disをr2にロードして。mcrでコントロールレジスタを読んで、Lctl_ID_disとのANDを取って、mrcで書き戻しています。。
I cache, D cacheをinvalidにしていますって、コメントのままですね。
ここからコントロールレジスタがたくさん出てくるので、フォーマットと定義を整理しておきましょう。
まずはレジスタのフォーマットです。
それぞれのフィールドの定義は/sys/arch/arm/include/armreg.hにあります。
209行目に戻り、ふたたび、c7のキャッシュまわりです。
,c7,c10,4 ; Data Synchronization Barrier operation.」と書いてあります。どういうことでしょう?
どうやら、昔はDrain the write buffersと呼ばれていたそうです。マニュアルを読んでもまるで自信はないですが、どうやらバリアというだけあって、この命令より前のメモリの操作やらキャッシュやらの操作が完了するまで待ちますよ、ってな感じの動きをするようです。
たしかに、ここまでいろいろキャッシュの操作をしてきたので、それらの操作がちゃんと終わるまで待ちましょう、という命令のようです。
mcr, mrc命令はマニュアルを拾い読みするだけでは理解に至らないことが多くて苦戦します。
今回読むのは次の部分です。
194 /*
195 * In theory, because the MMU is off, we shouldn't need all of this,
196 * but let's not take any chances and do a typical sequence to set
197 * the Translation Table Base.
198 */
199 mov r0, #0 /* SBZ */
200 Invalidate_I_cache(r0)
201
202 mcr p15, 0, r0, c7, c14, 0 /* Clean and Invalidate Entire Data Cache */
203
204 ldr r2, Lctl_ID_dis /* Disable I+D caches */
205 mrc p15, 0, r1, c1, c0, 0 /* " " " */
206 and r1, r1, r2 /* " " " */
207 mcr p15, 0, r1, c1, c0, 0 /* " " " */
208
209 mcr p15, 0, r0, c7, c10, 4 /* Drain the write buffers. */
まずはコメントです。
194 /*
195 * In theory, because the MMU is off, we shouldn't need all of this,
196 * but let's not take any chances and do a typical sequence to set
197 * the Translation Table Base.
198 */
うーん。どう訳すんでしょう。理論上、MMUはオフなので、これから行う操作がすべて必要ではないけれど、この辺でやるしかないので、TTB(Translation Table Base)をセットする典型的な手順を実行します、って感じですかねぇ。
まぁ、先に進みましょうか。
199 mov r0, #0 /* SBZ */
200 Invalidate_I_cache(r0)
SBZって何かとしらべたところ、SBZ = Should Be Zeroの略なんですね。ちなみに、SBO = Should Be Oneの略のようです。movでレジスタr0をゼロにしてInvalidate_I_cache(reg)を実行します。
Invalidate_I_cache(reg)はずいぶん最初のほうに記述がありました。
92 /*
93 * Workaround Erratum 411920
94 *
95 * - value of arg 'reg' Should Be Zero
96 */
97 #define Invalidate_I_cache(reg) \
98 .p2align 5; \
99 mcr p15, 0, reg, c7, c5, 0; /* Invalidate Entire I cache */ \
100 mcr p15, 0, reg, c7, c5, 0; /* Invalidate Entire I cache */ \
101 mcr p15, 0, reg, c7, c5, 0; /* Invalidate Entire I cache */ \
102 mcr p15, 0, reg, c7, c5, 0; /* Invalidate Entire I cache */ \
103 nop; \
104 nop; \
105 nop; \
106 nop; \
107 nop; \
108 nop; \
109 nop; \
110 nop; \
111 nop; \
112 nop; \
113 nop;
Errata 411920に対応するためのI cacheを0にクリアします。ちなみに、I cacheはInstruction cacheでD cacheはData cacheです。
c7はキャッシュ操作のレジスタです。ARM1176JZ-S™ Technical Reference Manualに、「MCR p15, 0,
なんでかわかりませんが、4回ほど連発してますね。
このあたりから、マニュアルと首っ引きで調べる感じです。
それでは、202行目に戻りましょう。
202 mcr p15, 0, r0, c7, c14, 0 /* Clean and Invalidate Entire Data Cache */
これも「MCR p15, 0, さっきがインストラクションキャッシュだったので、今度はデータキャッシュですね。
進めましょう。
204 ldr r2, Lctl_ID_dis /* Disable I+D caches */
205 mrc p15, 0, r1, c1, c0, 0 /* " " " */
206 and r1, r1, r2 /* " " " */
207 mcr p15, 0, r1, c1, c0, 0 /* " " " *
mrc, mcr命令にあるc1は Control Registerです。Lctl_ID_disをr2にロードして。mcrでコントロールレジスタを読んで、Lctl_ID_disとのANDを取って、mrcで書き戻しています。。
I cache, D cacheをinvalidにしていますって、コメントのままですね。
ここからコントロールレジスタがたくさん出てくるので、フォーマットと定義を整理しておきましょう。
まずはレジスタのフォーマットです。
| 31-30 | 29 | 28 | 27-26 | 25 | 24 | 23 | 22 | 21 | 20-19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6-4 | 3 | 2 | 1 | 0 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| SBZ | FA | TR | SBZ | EE | VE | XP | U | FI | SBZ | IT | SBZ | DT | L4 | RR | V | I | Z | F | R | S | B | SBO | W | C | A | M |
/* CPU control register (CP15 register 1) */
#define CPU_CONTROL_MMU_ENABLE 0x00000001 /* M: MMU/Protection unit enable */
#define CPU_CONTROL_AFLT_ENABLE 0x00000002 /* A: Alignment fault enable */
#define CPU_CONTROL_DC_ENABLE 0x00000004 /* C: IDC/DC enable */
#define CPU_CONTROL_WBUF_ENABLE 0x00000008 /* W: Write buffer enable */
#define CPU_CONTROL_32BP_ENABLE 0x00000010 /* P: 32-bit exception handlers */
#define CPU_CONTROL_32BD_ENABLE 0x00000020 /* D: 32-bit addressing */
#define CPU_CONTROL_LABT_ENABLE 0x00000040 /* L: Late abort enable */
#define CPU_CONTROL_BEND_ENABLE 0x00000080 /* B: Big-endian mode */
#define CPU_CONTROL_SYST_ENABLE 0x00000100 /* S: System protection bit */
#define CPU_CONTROL_ROM_ENABLE 0x00000200 /* R: ROM protection bit */
#define CPU_CONTROL_CPCLK 0x00000400 /* F: Implementation defined */
#define CPU_CONTROL_SWP_ENABLE 0x00000400 /* SW: SWP{B} perform normally. */
#define CPU_CONTROL_BPRD_ENABLE 0x00000800 /* Z: Branch prediction enable */
#define CPU_CONTROL_IC_ENABLE 0x00001000 /* I: IC enable */
#define CPU_CONTROL_VECRELOC 0x00002000 /* V: Vector relocation */
#define CPU_CONTROL_ROUNDROBIN 0x00004000 /* RR: Predictable replacement */
#define CPU_CONTROL_V4COMPAT 0x00008000 /* L4: ARMv4 compat LDR R15 etc */
#define CPU_CONTROL_FI_ENABLE 0x00200000 /* FI: Low interrupt latency */
#define CPU_CONTROL_UNAL_ENABLE 0x00400000 /* U: unaligned data access */
#define CPU_CONTROL_XP_ENABLE 0x00800000 /* XP: extended page table */
#define CPU_CONTROL_V_ENABLE 0x01000000 /* VE: Interrupt vectors enable */
#define CPU_CONTROL_EX_BEND 0x02000000 /* EE: exception endianness */
#define CPU_CONTROL_NMFI 0x08000000 /* NMFI: Non maskable FIQ */
#define CPU_CONTROL_TR_ENABLE 0x10000000 /* TRE: */
#define CPU_CONTROL_AF_ENABLE 0x20000000 /* AFE: Access flag enable */
#define CPU_CONTROL_TE_ENABLE 0x40000000 /* TE: Thumb Exception enable */
ファイル後半で定義されているコントロールレジスタに関連するのは次の四つ (Lcontrol_set, Lcontrol_clr, Lcontrol_wax, Lctl_ID_dis) になります。waxって何でしょうねぇ。
268 /* bits to set in the Control Register */
269 Lcontrol_set:
270 .word CPU_CONTROL_MMU_ENABLE | \
271 CPU_CONTROL_AFLT_ENABLE | \
272 CPU_CONTROL_DC_ENABLE | \
273 CPU_CONTROL_WBUF_ENABLE | /* not defined in 1176 */ \
274 CPU_CONTROL_32BP_ENABLE | \
275 CPU_CONTROL_32BD_ENABLE | \
276 CPU_CONTROL_LABT_ENABLE | \
277 CPU_CONTROL_SYST_ENABLE | \
278 (1 << 16) | /* SBO - Global enable for data tcm */ \
279 (1 << 18) | /* SBO - Global enable for insn tcm */ \
280 CPU_CONTROL_IC_ENABLE
281
282
283 /* bits to clear in the Control Register */
284 Lcontrol_clr:
285 .word 0
286
287 /* bits to "write as existing" in the Control Register */
288 Lcontrol_wax:
289 .word (3 << 30) | \
290 (1 << 29) | \
291 (1 << 28) | \
292 (3 << 26) | \
293 (3 << 19) | \
294 (1 << 17) | \
295 (1 << 10)
296
297 /* bits to disable the caches */
298 Lctl_ID_dis:
299 .word ~(CPU_CONTROL_IC_ENABLE|CPU_CONTROL_DC_ENABLE)
それぞれを一覧にしてみます。Lcontrol_clrは全部0なので省略です。| 定義 | 31-30 | 29 | 28 | 27-26 | 25 | 24 | 23 | 22 | 21 | 20-19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6-4 | 3 | 2 | 1 | 0 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| SBZ | FA | TR | SBZ | EE | VE | XP | U | FI | SBZ | IT | SBZ | DT | L4 | RR | V | I | Z | F | R | S | B | SBO | W | C | A | M | |
| Lctl_ID_dis | 1 1 | 1 | 1 | 1 1 | 1 | 1 | 1 | 1 | 1 | 1 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | 1 | 1 | 1 | 1 | 111 | 1 | 0 | 1 | 1 |
| Lcontrol_wax | 1 1 | 1 | 1 | 1 1 | 0 | 0 | 0 | 0 | 0 | 1 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 000 | 0 | 0 | 0 | 0 |
| Lcontrol_set | 0 0 | 0 | 0 | 0 0 | 0 | 0 | 0 | 0 | 0 | 0 0 | 1 | 0 | 1 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 1 | 0 | 111 | 1 | 1 | 1 | 1 |
209 mcr p15, 0, r0, c7, c10, 4 /* Drain the write buffers. */
うーん、マニュアルでは「MCR p15,0,どうやら、昔はDrain the write buffersと呼ばれていたそうです。マニュアルを読んでもまるで自信はないですが、どうやらバリアというだけあって、この命令より前のメモリの操作やらキャッシュやらの操作が完了するまで待ちますよ、ってな感じの動きをするようです。
たしかに、ここまでいろいろキャッシュの操作をしてきたので、それらの操作がちゃんと終わるまで待ちましょう、という命令のようです。
mcr, mrc命令はマニュアルを拾い読みするだけでは理解に至らないことが多くて苦戦します。
コメント(0件)
- TB-URL http://www.tokuda.net/diary/0812/tb/