linux-0.01 読み (3)

とりあえず、うにまがの_Linux のブートプロセスをみる_の 2002.5 〜 2002.9 なあたりのソレを読みつつ、ポイントを控えるかも。。

リアルモードからプロテクトモードへの移行

cr0 レジスタの最下位ビットが云々、との記述がある。1 ならプロテクトモードで 0 ならリアルモードとの事。
このあたりを切り口にうにまが読んでたらなんとなく見えてきたようなそうでも無いような。とりあえず setup_paging な末端な以下の処理は

	orl $0x80000000,%eax
	movl %eax,%cr0		/* set paging (PG) bit */
	ret			/* this also flushes prefetch-queue */

諸々の準備を終えて cr0 な最下位ビットを 1 にしていますね。あるいは startup_32 な先頭部分の以下なソレは

startup_32:
	movl $0x10,%eax
	mov %ax,%ds
	mov %ax,%es
	mov %ax,%fs
	mov %ax,%gs
	lss stack_start,%esp
	call setup_idt
	call setup_gdt
	movl $0x10,%eax		# reload all the segment registers
	mov %ax,%ds		# after changing gdt. CS was already
	mov %ax,%es		# reloaded in 'setup_gdt'
	mov %ax,%fs
	mov %ax,%gs
	lss stack_start,%esp

セグメントレジスタを 0x10 で初期化しつつ idt と gdt を設定して再設定してるように見えます。ただ、stack_start を esp に云々という処理は理解が微妙。
あるいはその直後の以下な部分

	xorl %eax,%eax
1:	incl %eax		# check that A20 really IS enabled
	movl %eax,0x000000
	cmpl %eax,0x100000
	je 1b

は A20 が有効になってるかどうかなチェック (コメントにも記述あり) に見えるんですが、これって A20 が有効になるまではループし続けるんじゃないのか。
A20 がマスクされてたら 0x000000 と 0x100000 は同じソレを指すはずなので、これって A20 が有効になってるチェックなはずなんだけど、何故にここでなのかが微妙。
ここは一旦スルーするとして以降のソレが以下。

	movl %cr0,%eax		# check math chip
	andl $0x80000011,%eax	# Save PG,ET,PE
	testl $0x10,%eax
	jne 1f			# ET is set - 387 is present
	orl $4,%eax		# else set emulate bit
1:	movl %eax,%cr0
	jmp after_page_tables

ええとコメント通り、cr0 の PG、ET、PE を eax に保存してます。で、ET がセットされているかどうかを確認して

	testl $0x10,%eax

equal でなければ jmp してて、セットされてなかったらセットした後で cr0 に戻しております。

とりあえず

全然謎だらけなんですが、今からもう少しがつっと記事を読んでみます。

segment descriptor はプロテクトモードに移行する前に自分で作れ、という記述がある。てか、連載一発目でハードルが物凄く高いんですがorz
segment descriptor table という名前が付いてるようです。ってかプロテクトモードのセグメント・ワールドはさらに複雑に、という記述があるなorz
明日も会社に持ってって、って思ってますが多分読むヒマは無いはず。