調べているのはここにあるソース。
http://gsd.unex.es/projects/minixsmp/
ソースにコメントがちゃんと書いてあるのでこれを読めば良いのでうれしい。
trampolineは4段階のステップで行われていますよ。
!*===========================================================================* !* init_ap * !*===========================================================================* ! This is the entry point for second processor (AP) to start executing ! (the linux trampoline) ! At this point, we are in 16-bit real mode, with no stack ! ip register is 0 ! cs points to something like 000xx000h ! ds is unusable due to code relocation from where assembler links to ! somewhere like 000xx000h ! ! Actions: ! 1. Mark data area to tell the BSP we are running in real mode ! 2. Read values of many registers to prepare environment to jump ! into protected mode in same conditions as BSP ! 3. Change to protected mode ! 4. Jump to protected mode trampoline section ! ! NOTE that this code MUST be assembled as 16-bit ! Using C16 (o16+a16) marks, we force the assember to generate 16-bit ! instructions, but it introduces operand-size modifiers machine code ! (bytes 66h and 67h before each instruction) because when in 32-bit ! protected mode, 66h & 67h force the cpu to interpret next instruction ! as 16-bit. But when in 16-bit real mode, 66h & 67h force the cpu to ! execute next instruction as 32-bit. So we need to delete these marks from ! trampoline code. As trampoline must be relocated to an address ! 4Kb-page-aligned, then the marks must be replaced by <nop> code (90h) !
それでは、ソースを見ていくと・・・
.sect .data .align 16 #define C16 o16 a16 _init_ap: C16 jmp _skip_data _data_area: ! Space for variables _gdtr_data: .data2 0x0000 ! gdt limit .data4 0x00000000 ! addr _idtr_data: .data2 0x0000 ! idt limit .data4 0x00000000 ! addr _esi_data: .data4 0x00000000 ! esi _edi_data: .data4 0x00000000 ! edi _ebp_data: .data4 0x00000000 ! ebp _skip_data:
コードの最初のほうは定数定義していて、jmpの処理は定数定義部分を飛ばしてコードの本体にジャンプするためのもの。
! Mark life_flag to tell BSP we are running C16 cli ! safe from interrupts C16 mov ax, cs C16 mov ds, ax ! ds= cs (_init_ap)
最初のステップは「1. Mark data area to tell the BSP we are running in real mode」の部分で、
cliで割り込みを禁止して、csレジスタの内容をaxレジスタを経由して、dsレジスタにコピー。
そうすると、コメントにあるようにds==csになる。
! Prepare environment to jump into protected mode C16 lgdt ( [ TR_GDTR_OFFSET ] ) C16 lidt ( [ TR_IDTR_OFFSET ] )
2ステップ目はプロテクトモードに移行する準備としてgdtとidtの設定をする。
/* Offsets from trampoline start to data areas */ #define TR_GDTR_OFFSET _gdtr_data - _init_ap #define TR_IDTR_OFFSET _idtr_data - _init_ap
TR_XXXXはxmp.hで定義しているマクロで、gdtrとかidtrのアドレスを計算。
そして、lgdt、lidt命令でgdt、idtの設定をする。
3ステップ目でcpuのcr0レジスタの最下位ビットを1にしてプロテクトモードに移行する。
この辺はx86アーキテクチャのカーネルに興味のある人には馴染みの処理かと・・
! Into protected mode mov eax, cr0 orb al, 1 mov cr0, eax
最後の4ステップ目はjmpf命令使ってプロテクトモードで続きの処理を行っていく。
! Far jmp to start with 32 bit execution. ! Jump to a .text CS-addressed point C16 jmpf CS_SELECTOR:_trampoline_pm _end_init_ap: hlt
jmpfで飛ぶところは_trampoline_pmでこいつも、toramplineと同じくxmp.sに存在。
_trampoline_pmの主要な処理はプロテクトモード下で動くための設定(スタックとかTSSとか)をして、mp.cにいるap_main()を呼び出す。
詳細は次回見ていく。