14
13

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Raspberry Pi2(Linux Kernel)のブートシーケンスを読む(その3) アーキテクチャ依存部

Last updated at Posted at 2016-03-20

##前回
「ENTRY(stext)でproc_info_list構造体へのポインタを取得するまで」を説明しました。

##Kernel内のENTRY(stext)の続き(PHYS_OFFSET取得まで)

linux-rpi-4.1.y/arch/arm/kernel/head.S
#ifdef CONFIG_ARM_LPAE
	mrc	p15, 0, r3, c0, c1, 4		@ read ID_MMFR0
	and	r3, r3, #0xf			@ extract VMSA support
	cmp	r3, #5				@ long-descriptor translation table format?
 THUMB( it	lo )				@ force fixup-able long branch encoding
	blo	__error_lpae			@ only classic page table format
#endif

まず、上記の処理を通るには、
コンフィグでLPAE(Large Physical Address Extension)を有効にする必要があります。
LPAE(仮想化拡張機能)は、ページテーブルを2つ用意する手法で、
ハイパーバイザを使用した際のスループットを維持するための仕組みのようです。
ちなみに、前回の説明でハイパーバイザのインストール処理を飛ばしたので、
上記の説明も割愛いたします(後日、ハイパーバイザと共に別記事を書き、リンクを貼ります)。

次の処理に進みます。

linux-rpi-4.1.y/arch/arm/kernel/head.S
#ifndef CONFIG_XIP_KERNEL
	adr	r3, 2f
	ldmia	r3, {r4, r8}
	sub	r4, r3, r4			@ (PHYS_OFFSET - PAGE_OFFSET)
	add	r8, r8, r4			@ PHYS_OFFSET
#else
	ldr	r8, =PLAT_PHYS_OFFSET		@ always constant in this case
#endif

上記の処理は、 Kernel Execute-In-Place(XIP)が有効/無効で分岐します。
ここでXIPとは、RAMにコード(.textセクションの内容、関数)を展開する事なく、
不揮発性フラッシュメモリ上のコードに直接アクセスして実行する形式です。
私はXIPを使用した事がないので、アドレス空間の問題とか気になります。

ここでの処理の目的は、RAMに展開したデータが物理アドレス0x0000_0000番地から始まらない場合(開始アドレスが0x0000_0000 + PHYS_OFFSETの場合)に備えて、
r8にPHYS_OFFSETを入れる事です。

XIPが有効の場合は、r8にPLAT_PHYS_OFFSETを格納します。
PLAT_PHYS_OFFSETは、
linux-rpi-4.1.y/arch/arm/mach-bcm2709/include/mach/memory.h内で、
#define PLAT_PHYS_OFFSET UL(CONFIG_PHYS_OFFSET)と定義されています。
CONFIG_PHYS_OFFSETは、
arch/arm/configs/bcm2709_defconfig内で、CONFIG_PHYS_OFFSET=0と定義されています。
「値が0なら、この処理は不要では?」と思いますが、
このオフセット値は__virt_to_phys()マクロで使用されるため、定義する必要があります。

XIPが無効の場合、r3にPAGE_OFFSETへのラベル(アドレス)を格納します。
PAGE_OFFSETへのラベル(2:)は、head.S内にあります。

linux-rpi-4.1.y/arch/arm/kernel/head.S
2:	.long	.
	.long	PAGE_OFFSET

ここからがアセンブリ言語が読めなくて、
ldmia命令によって、r3(ラベルへのアドレス)から、r4、r8に値をロードされる筈。
どのレジスタに、どの値を?
最終的には、r8にPHYS_OFFSETが格納されますが、それまでの加算減算も理解できてません。
後日、追記します。

この時点での汎用レジスタの状態は、以下の通りです。

r1 = machine number
r2 = dtb
r8 = phys_offset
r9 = cpu_id
r10 = proc_info

##Kernel内のENTRY(stext)の続き(ページテーブルの作成まで)

linux-rpi-4.1.y/arch/arm/kernel/head.S
	bl	__vet_atags
#ifdef CONFIG_SMP_ON_UP
	bl	__fixup_smp
#endif
#ifdef CONFIG_ARM_PATCH_PHYS_VIRT
	bl	__fixup_pv_table
#endif
	bl	__create_page_tables

__vet_atagsの定義は、linux-rpi-4.1.y/arch/arm/head-common.S内にあります。
この関数では、r2に格納されているポインタ(ATAGS or DTB)の妥当性を確認します。
r2の内容と妥当性を確認するための定数とを比較し、一致しない場合はr2を0にします。
一致している場合は、何も行いません。

__fixup_smp(linux-rpi-4.1.y/arch/arm/head.S)の処理は、
CONFIG_SMP_ON_UP(SMP=Symmetric Multi-Processors)が有効の場合に通る。
Raspberry Pi2のCPUは複数のコアが搭載されているので、SMPに対応しています。
肝心の処理ですが、CPUがSMPに対応しているかどうかの確認以外、
読み取ることができませんでした(後日、追記します)。

__fixup_pv_table(linux-rpi-4.1.y/arch/arm/head.S)の処理も、
CONFIG_ARM_PATCH_PHYS_VIRTが有効の場合のみ通ります。
この関数では、arch/arm/include/asm/memory.h内の「仮想アドレス-物理アドレス」を
変換する関数やマクロが使用する変数を決定します。

__create_page_tables(linux-rpi-4.1.y/arch/arm/head.S)では、
r4にページテーブルのアドレスを格納します。その後の処理はページテーブルの作成です。

##Kernel内のENTRY(stext)の続き(MMUの有効化まで)

	ldr	r13, =__mmap_switched		@ address to jump to after
						@ mmu has been enabled
	adr	lr, BSYM(1f)			@ return (PIC) address
	mov	r8, r4				@ set TTBR1 to swapper_pg_dir
	ldr	r12, [r10, #PROCINFO_INITFUNC]
	add	r12, r12, r10
	ret	r12
1:	b	__enable_mmu
ENDPROC(stext)

__mmap_switched(linux-rpi-4.1.y/arch/arm/head-common.S)は、
MMUをONにした後に実行するstart_kernel(linux-rpi-4.1.y/init/main.c)を
r13(SP)に格納する。
ここでの処理は、こちらのサイトが参考になります。

最後に、__enable_mmuでMMUがONになった後、
start_kernel(アーキテクチャに依存しない処理、C言語)に処理が移ります。

##疑問点
・XIPが有効の場合は、何故PLAT_PHYS_OFFSETが0なのか。
・__fixup_smpの処理内容
・アセンブラをステップ実行する方法

##次回
start_kernel()のカナリアコードをスタックに埋め込むまでを説明しています。

##参考
ARM startup code analysis Linux

14
13
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
13

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?