Minix smp
Upcoming SlideShare
Loading in...5
×
 

Minix smp

on

  • 2,108 views

第2回カーネル/VM探検隊の資料

第2回カーネル/VM探検隊の資料

Statistics

Views

Total Views
2,108
Views on SlideShare
2,108
Embed Views
0

Actions

Likes
1
Downloads
9
Comments
0

0 Embeds 0

No embeds

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

Minix smp Minix smp Presentation Transcript

  • MinixとSMP〜Minix SMPを読んでみる〜 @masami256
  • Agenda• Minix SMP?• Minix SMP初期化の流れ• トランポリンコード
  • Minix SMP?• Minix SMPはMinix2.0.0でSMPを実装 o 作者はJesús M. Álvarez Llorenteさん o プロジェクトのページはこちら  http://gsd.unex.es/projects/minixsmp/  ソースや論文(スペイン語)がダウンロード可能• 対象アーキテクチャはx86
  • 基本用語• MP:Multi Processor• BSP:Boot Strap Processor o コンピュータが起動したときに動いたCPU• AP:Application Processor o 2〜n個目のCPU• APIC(Advanced Programmable Interrupt Controller) o x86における割り込みコントローラ• Local APIC o CPU内部に実装されていて、外部からの割り込みをコントロールする• IO APIC o I/Oデバイスから受け取った割り込みをCPUにリダイレクトする• IPI(Interprocessor Interrupt) o プロセッサ間の割り込み
  • Agenda• Minix SMP?• Minix SMP初期化の流れ• トランポリンコード
  • SMPのセットアップ手順
  • SMPのセットアップ手順(続き)
  • 実際の流れを追いかけよう電源ON〜main()の間はSMPに関する処理はないので飛ばします
  • SMPのセットアップ手順
  • enable_cpu()の処理概要• main()から呼ばれた場合は、BSPの有効化をする• 今動いているCPU(this_cpu)が有効化済みかチェック• 有効化しようとしているCPUがthis_cpuかチェック• 同じ場合 o enable_apic_ints()を呼んでAPCI・割り込みの有効化 o 次に動くプロセスの選択• 違う場合 o CPUに割り込みメッセージを送信
  • enable_cpu()の処理PUBLIC void enable_cpu(int cpu, int echo) { ・・・・ if (cpu_available[cpu]==CPU_ENABLED) return; /* A CPU only can only enable its own APIC */ if (cpu==this_cpu) { enable_apic_ints(); cpu_available[cpu]=CPU_ENABLED; lock_pick_proc(); if (echo) printk("CPU%d enabledn",cpu); } else { interrupt_cpu(cpu,MP_CM_ENABLE,echo); }}
  • this_cpu#define this_cpu f_this_cpu() f_this_cpuはTHIS_CPU_SHORTマクロを呼び出すのがメインの処理。 #define THIS_CPU_SHORT(reg) ; mov edx, (_local_apic_base) ; add edx, 0x20 ; mov reg, FLAT_DS_SELECTOR ; mov ds, reg ; mov reg, (edx) ; and reg, 0x0F000000 ; shr reg, 6*4local_apic_baseは以下のようにmp.cにて定義。u32_t local_apic_base=0x0FEE00000;MPの仕様書によると、APICのデフォルトベースアドレス0FEC0_0000hと0FEE0_0000hと記述されている。Minix SMPでは_local_apic_baseの値は0x0FEE00000としています。
  • enable_apic_ints()の処理reg = LOCAL_APIC_READ(LOCAL_APIC_SPIV);reg |= (1<<ENABLE_APIC_SHIFT); /* Enable APIC */LOCAL_APIC_WRITE(LOCAL_APIC_SPIV, reg);reg = LOCAL_APIC_READ(LOCAL_APIC_LVTL0);reg &= ~(7<<LVT_DM_SHIFT); /* clear delivery mode */reg &= ~(1<<LVT_MASKED_SHIFT); /* unmask LINTIN0 */reg |= (LVT_DM_EXTINT<<LVT_DM_SHIFT); /* ExtINT at LINTINT0 */LOCAL_APIC_WRITE(LOCAL_APIC_LVTL0, reg);reg = LOCAL_APIC_READ(LOCAL_APIC_LVTL1);reg &= ~(7<<LVT_DM_SHIFT); /* clear delivery mode */reg &= ~(1<<LVT_MASKED_SHIFT); /* ummask LINTIN1 */reg |= (LVT_DM_NMI<<LVT_DM_SHIFT); /* NMI at LINTINT1 */LOCAL_APIC_WRITE(LOCAL_APIC_LVTL1, reg);
  • LOCAL APICへの読み書きvoid LOCAL_APIC_WRITE(u32_t reg, u32_t val) { phys_copy_dword( vir2phys(&val), local_apic_base+reg );}u32_t LOCAL_APIC_READ(u32_t reg) { u32_t val; phys_copy_dword( local_apic_base+reg, vir2phys(&val) ); return val;}
  • SMPのセットアップ手順
  • mp_start()の処理概要• load_fps()〜free_trampoline()までの処理を順番に呼び出し• 関数の終了時点でAPが起動するようになる
  • mp_start()の処理void mp_start() { ・・・・ if (load_fps()) { if (load_mph()) { process_mp_configuration(); if ((trampoline_addr=find_trampoline())) { FOR_EACH_AP(cpu) { ・・・・ send_init_ipi(trampoline_addr, cpu); send_startup_ipi(trampoline_addr, cpu); } free_trampoline(trampoline_addr); }
  • SMPのセットアップ手順
  • load_fps()概要• MP floating structure pointer(fps)を読み込みます• MP floating structure pointer? o 16バイトの大きさのテーブル o MP機能に関する情報を保持しています  特に「MP Configuration table」のアドレスを保持し ているのが重要なポイントです o 規程のアドレス内に存在(MPの仕様書で定義)  Extended BIOS Data Area(EBDA)の最初の1KB以内  EBDAが定義されていない場合は、ベースメモリ 領域の最後の1KB(ベースメモリ領域が640KBな ら639-640KBの範囲)以内  0F0000h〜0FFFFFの範囲(BIOSのROM内)
  • fps構造体struct floating_pointer { char fp_signature[4]; /* must be _MP_ */ u32_t fp_mp_table; /* address to MP table */ u8_t fp_length; /* FPS size in 16-byte parragraphs */ u8_t fp_version; /* version number: 04h for 1.4 */ u8_t fp_cheksum; /* bytes in FPS must sum 0 */ u8_t fp_sd_config_num; /* standar config number (0 for none) */ u8_t fp_imcrp; /* bit 7 is IMCR present and PIC mode */ char unused[3]; /* last 3 bytes are reserved */};
  • fps構造体• fpsの先頭4バイトはシグネチャです o シグネチャは"_MP_"であることと規定されてます• OSがfpsを探すときはfpsが置かれているべきアドレスを起点 とします o そこから16バイトおきにメモリの内容を読み込みます• 読み込んだ16バイトの領域がfpsかは、シグネチャとチェッ クサムで確認します• チェックサムの確認はfpsの領域(16バイト)を1バイトずつ読 み込んで数値として足し算していき、結果が0ならOKとなり ます
  • load_fps()処理内容最初にシグネチャのチェックを実行/* fisrt look for signature */for (i=0; i<4; i++) if (fps->fp_signature[i] != SIGN_FPS[i]) return 0;シグネチャが正しければチェックサムを計算 /* then calculate checksum*/ data=(unsigned char *)fps; checksum=0; for (i=0; i<sizeof (struct floating_pointer); i++) checksum+= data[i]; return (!checksum); /* checksum ok if sums 0 */
  • SMPのセットアップ手順
  • load_mph()概要• fpsを読み込めたら次はMP Configuration table Header(mpch)を読み込みます• mpchが置かれているアドレスは fps構造体のfp_mp_table から取得します• MP Configuration table Header? o 「MP Configuration table」のヘッダです(キリッ o 5種類あり、サイズも各テーブルで違います•  MP Configuration tableを読み込むために必要な情報をこ こから取得します• load_mph()で使用するのは、2個のフィールドだけです o fpsと同じく、シグネチャとチェックサム
  • MP Configuration table• テーブルの種類はENTRY TYPEにより識別• ENTRY TYPEは5種類• 各テーブルはメモリ上で連続• 各項目はオプショナル(必須ではない) Entry Description Entry Type Code Processor 0 Bus 1 I/O APIC 2 I/O Interrupt Assignment 3 Local Interrupt Assignment 4
  • mp_config_headerの構造体/* Describes the estruct of MP configuration table header */struct mp_config_header { char mpch_signature[4]; /* must be "PCMP" */ u16_t mpch_length; /* base table size including header */ u8_t mpch_version; /* MP specification version number*/ u8_t mpch_checksum; /* base table + checksum must sum 0 */ char mpch_oem_id[8]; /* manufacturer id (space filled) */ char mpch_product_id[12]; /* product id (space filled) */ u32_t mpch_oem_table; /* optional manufacturer table address */ u16_t mpch_oem_table_size; /* manufacturer table size */ u16_t mpch_entry_count; /* entry count in MP table */ u32_t mpch_apic_addr; /* IO address for local APIC */ u16_t mpch_extended_length; /* extended table length */ u8_t mpch_extended_checksum; /* extended table checksum */ char mpch_reserved; /* unused */};
  • load_mph()処理内容シグネチャのチェック /* first match the signature */ for (i=0; i<4; i++) if (mph.mpch_signature[i] != SIGN_MP_C_HEADER[i] ) return 0;チェックサムのチェック /* then calculate checksum */ checksum=0; for (i=0; i<mph.mpch_length; i++) { /* the complete table is in another segment, so we need copy each byte into kernel address space (mph is only the header) */ phys_copy(fps.fp_mp_table+i, vir2phys(&data), 1); checksum +=data; } return (!checksum); /* checksum ok if sums 0 */
  • SMPのセットアップ手順
  • process_mp_configuration()概要• MP Configuration table数分(mph.mpch_entry_count)データ の読み込みを行います• 1個目のMP Configuration tableのアドレスは以下のように求 めます o next=fps.fp_mp_table+sizeof (struct mp_config_header);• アドレスが分かってもENTRY TYPEが分からないので最初に 1バイトだけ読みこんでENTRY TYPEの判別をします• ENTRY TYPEが分かったら、そのENTRY TYPEに応じた データの読み込みをします• ENTRY TYPEは5種類ですが、そのうち3種類はMinix SMP実 装では特に使用せずに読み飛ばしています
  • process_mp_configuration()処理内容while (i-- > 0) { phys_copy(next, vir2phys(&this_entry), 1); switch (this_entry) { case CPU_ENTRY_ID : // Processor ・・・ case BUS_ENTRY_ID : // Bus ・・・ case IO_APIC_ENTRY_ID : // I/O APIC ・・・ case IO_INT_ENTRY_ID : // I/O Interrupt Assignment ・・・ case LOCAL_INT_ENTRY_ID : // Local Interrupt Assignment ・・・ default : ・・・ }}
  • Processor Entriesの構造体struct cpu_entry { u8_t ce_type; /* 0 for this type */ u8_t ce_local_apic_id; /* local APIC id number */ u8_t ce_local_apic_ver; /* local APIC version */ u8_t ce_flags; /* CPU enabled and CPU is bootstrap */ u32_t ce_signature; /* CPU type */ u32_t ce_features; /* features of this CPU */ char reserved[8]; /* reserved */};
  • Processor Entriesの処理概要• CPUが有効かチェックする• CPU FLAGSフィールド(ce_flags)を調べる o 大きさは1バイトで2種類(各1bit)のビットがあります o ENビットが0なら、このCPUは無効  無効の場合、このCPUは使用禁止 o BPビットが1なら、このCPUはBSP• CPUが有効かどうかのチェックは必須です
  • Processor Entriesの処理 case CPU_ENTRY_ID : if (++cpu_count > 2) ADDS_MP_STATUS("MP PANIC: only 2 cpus currentlysupported!n"); phys_copy(next,vir2phys(&ce),sizeof(struct cpu_entry)); next+=sizeof(struct cpu_entry); PRINT_CPU_ENTRY(cpu); if ((ce.ce_flags & CE_EN_FLAG_MASK)==0) ADDS_MP_STATUS("MP PANIC: disabled apics notcurrently supportedn"); break;
  • I/O APIC Entriesの構造体struct io_apic_entry { u8_t ae_type; /* 2 for this type */ u8_t ae_id; /* IO APIC identification */ u8_t ae_version; /* IO APIC version number */ u8_t ae_flags; /* bit 0 means enabled */ u32_t ae_address; /* IO APIC memory address */};
  • I/O APIC Entriesの処理概要• I/O APIC Entriesで見なければいけないところ o ENビット(1bit)  CPU EntriesのENビットと同じく、有効なら1 になる o I/O APIC ADDRESS  APICへ読み書きするときに使うアドレス
  • I/O APIC Entriesの処理 case IO_APIC_ENTRY_ID : if (++apic_count > 1) ADDS_MP_STATUS("MP PANIC: only 1 I/O APICcurrently supported!n"); phys_copy(next,vir2phys(&ae),sizeof(struct io_apic_entry)); next+=sizeof(struct io_apic_entry); /*PRINT_IO_APIC_ENTRY(ae);*/ if ((ae.ae_flags & AE_EN_FLAG_MASK)==0) ADDS_MP_STATUS("MP PANIC: disabled apic notcurrently supported!"); io_apic_base=ae.ae_address; break;
  • SMPのセットアップ手順
  • find_trampoline()の処理概要• メモリ上でトランポリンコードを置く場所を探します• トランポリンコード? o トランポリン(時々間接的なジャンプベクトルと呼ばれ る)は、割り込み処理ルーチン、I/Oルーチンなどを示しな がらアドレスを保持する記憶域です。 次に、実行は、す ぐにトランポリンに飛びついて、飛び出るか、または弾 んで、したがって、用語はトランポリンです。  http://wapedia.mobi/en/Trampoline_(computers)• トランポリンコードはAPの初期化時に必要です o x86系CPUはリアルモードで起動するので、プロテクト モードに移行したりといった処理がAPも必要です
  • find_trampoline()の処理概要• トランポリンコードのサイズを計算• トランポリンコードを置ける場所の探索• GDT、IDTをレジスタにコピー• トランポリンコードを見つかった場所にコピー• トランポリンコード中のマシン語コードの書き換え
  • find_trampoline()の処理1 /* size of tampoline code */ u32_t tramp_len=(u32_t)end_init_ap-(u32_t)init_ap; • tramp_lenを設定している部分で使っている、名前は変数 じゃなくて、アセンブラコードのラベルです o トランポリンコードをラベルで囲ってます _init_ap: C16 jmp _skip_data ・・・ C16 jmpf CS_SELECTOR:_trampoline_pm_end_init_ap:
  • find_trampoline()の処理2 /* Look for a hole of free memory in each valid position of basememory */ /* For some reason 0x0000F000 is not valid!! so start form 0x10 */ for (addr8=0x11; addr8<0x100; addr8++) { if (addr8==0xA0) addr8=0xC0; /* vectors A0..BF are reserved */ addr=addr8<<12; /* aligned in 4kb boundaries */ for (i=0; i<tramp_len; i++) { phys_copy(addr+i, vir2phys(&c), 1); if (c) break; }• ループ先頭のif文は、MPの仕様書「B.4.2 USING STARTUP IPI」の説明と一致していて、A0-BFは予約済みだから使うな よ!とか、ページ境界は4KBだ!と説明が書いてあるので、 それに則ってます。
  • find_trampoline()の処理3 if (i==tramp_len) { /* Prepare and copy the tampoline */ copy_registers_to_trampoline(); phys_copy(vir2phys(init_ap), addr, tramp_len); disable_operand_size(addr,tramp_len); /*dump_trampoline(addr,tramp_len);*/ return addr; /* return it */ }
  • copy_registers_to_trampoline()の処理_copy_registers_to_trampoline: ! Copy gdt and idt sgdt (_gdtr_data) sidt (_idtr_data) ! Copy 32-bit regsiters mov eax, esi mov (_esi_data), eax mov eax, edi mov (_edi_data), eax mov eax, ebp mov (_ebp_data), eax ret
  • disable_operand_size()の処理void disable_operand_size(u32_t trampoline_addr, u32_t trampoline_sz) {/* Change operand-size modifier codes (66h & 67h) on trampolines machine code introduced by assembler and replace they with <nop> code (90h) *// ・・・・ while (trampoline_sz>1) { /* last byte not necessary to scan */ phys_copy(trampoline_addr, code_addr, 2); if ((code==0x6766)) { /* o16 a16 */ code=0x9090; /* nop nop */ phys_copy(code_addr, trampoline_addr, 2); trampoline_addr+=2; trampoline_sz-=2; } else { trampoline_addr++; trampoline_sz--; } }}
  • SMPのセットアップ手順
  • send_init_ipi()の処理概要• APを起動させる前にipiを初期化します• MPの仕様書「Appendix A System BIOS Programming Guidelines」と「Appendix B Operating System Programming Guidelines」あたりに詳しく書かれています
  • send_init_ipi()の処理1/* Reprogram warm reset: write code 0A at CMOS addr 0F */old_cmos=cmos_read(0x0F);cmos_write(0x0F, 0x0A);/* save old reset vector at 40:67 (dw) */phys_copy(0x467,vir2phys(&old_vector), sizeof(u32_t));• まず、CMOSに0Aを書き込んでPCをwarm resetします o PCの電源をOFFにしないで再起動• reset vectorのバックアップを取ります o 0x467の意味は「warm-reset vector, which is a doubleword pointer in system RAM location 40:67h」と説明があります
  • send_init_ipi()の処理2/* program reset vector to point at trampoline */value=(trampoline_addr >> 4); /* trampoline segment */phys_copy(vir2phys(&value), 0x469, sizeof(u16_t));value=(trampoline_addr & 0xF); /* trampoline offset */phys_copy(vir2phys(&value), 0x467, sizeof(u16_t));• トランポリンコードのアドレスをアドレス0x467、0x469に 書き込みます
  • send_init_ipi()の処理3/* send the IPI (assert) */apic_error_status(); /* first, clear previous errors */LOCAL_APIC_WRITE(LOCAL_APIC_ICR_HIGH, icr_h);LOCAL_APIC_WRITE(LOCAL_APIC_ICR_LOW, icr_l);wait_for_ipi_completion();/* send the IPI (deassert) */apic_error_status(); /* first, clear previous errors */icr_l ^= (1<<LEVEL_SHIFT); /* switch to deassert */LOCAL_APIC_WRITE(LOCAL_APIC_ICR_HIGH, icr_h);LOCAL_APIC_WRITE(LOCAL_APIC_ICR_LOW, icr_l);wait_for_ipi_completion();• しばらくデータの設定が続いてから、実際にデータを書き込 んでいきます
  • send_init_ipi()の処理4/* restore old reset vector and cmos shutdown code */phys_copy(vir2phys(&old_vector), 0x467, sizeof(u32_t));cmos_write(0x0F, old_cmos);• 最後に、バックアップしたreset verctorを書き戻します• これでIPIの初期化が終りです
  • SMPのセットアップ手順
  • send_startup_ipi()の処理概要• この関数は引数を2個受け取ります o trampoline_addrはトランポリンのアドレス o which_cpuは起動させたいcpu番号  this_cpuマクロで取得したcpu番号です• この関数でipiを有効にすることで、APが起動するようにな ります
  • send_startup_ipi()の処理1 /* put addr in 8 bit lower */ trampoline_addr = (trampoline_addr >> 12) & 0xFF; /* prepare to send STARTUP IPI */ icr_h = LOCAL_APIC_READ(LOCAL_APIC_ICR_HIGH); icr_l = LOCAL_APIC_READ(LOCAL_APIC_ICR_LOW);  ・・・・ icr_l |= (DELIVERY_STARTUP<<DELIVERY_SHIFT); /* stablish STARTUP */ icr_l |= (1 << LEVEL_SHIFT); /* level = assert */ icr_l &= ~(1 << TRIGGER_SHIFT); /* trigger = edge */ icr_l |= (PHYSICAL_DEST << DEST_MODE_SHIFT); /* destination = physical */ icr_l |= (DEST_FIELD << DEST_SHORT_SHIFT); /* destination by field */ icr_l |= trampoline_addr; /* vector field */ icr_h |= (which_cpu << DEST_FIELD_SHIFT); /* cpu to interrupt */
  • send_startup_ipi()の処理2/* send the IPI */apic_error_status();LOCAL_APIC_WRITE(LOCAL_APIC_ICR_HIGH, icr_h);LOCAL_APIC_WRITE(LOCAL_APIC_ICR_LOW, icr_l);wait_for_ipi_completion();• 書き込み方法はsend_init_ipi()と同じです• これで、APが起動します
  • APが起動したかの確認• send_startup_ipi()でAPを起動させたら、mp_start()で 本当に APが起動したか確認をします。 if (! AP_running()) { ADDS_MP_STATUS("nn*** WARNING! AP#"); ADDN_MP_STATUS(cpu,10,1); ADDS_MP_STATUS(" is not running ***nn");}
  • SMPのセットアップ手順
  • free_trampoline()の処理• トランポリンコードを置く場所を探したときに使用したア ドレスに0を書き込んで置きますvoid free_trampoline(u32_t addr) {/* Restore with 0s the memory zone used for trampoline */ char dummy=0; u32_t tramp_len=(u32_t)end_init_ap-(u32_t)init_ap; while (tramp_len--) phys_copy((u32_t)&dummy,addr++,1);}
  • Agenda• Minix SMP?• Minix SMP初期化の流れ• トランポリンコード
  • トランポリンコードの処理• トランポリンコードでは実際にどんなことをするのか? o Mark data area to tell the BSP we are running in real mode o Read values of many registers to prepare environment to jump into protected mode in same conditions as BSP o Change to protected mode o Jump to protected mode trampoline section• トランポリンコードはアセンブラのコードですが、最終的 にap_main()というCの関数を呼び出すまでが一連の処理です
  • トランポリンコードの処理
  • トランポリンコードの処理概要• リアルモードからプロテクトモードに移行し、次の処理に 進む o cs・dsレジスタの設定 o gdtr、idtrの設定 o プロテクトモード移行 o _trampolin_pmへセグメントジャンプ
  • トランポリンコード(データ定義).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: ! 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) ! Prepare environment to jump into protected mode C16 lgdt ( [ TR_GDTR_OFFSET ] ) C16 lidt ( [ TR_IDTR_OFFSET ] ) ! Into protected mode mov eax, cr0 orb al, 1 mov cr0, eax ! 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
  • トランポリンコードの処理
  • trampoline_pm()の処理概要• 各種レジスタの設定• TSSの設定 o Task State Segmentの略 o タスク状態の保存・復元に使用するデータ領域 o x86ではTSSを使ってタスクを切り替えることができる• スタックの設定• キャッシュの有効化• ap_main()のコール
  • trampoline_pm()の処理_trampoline_pm: ! We are in protected mode. Load AP registers as in BSP ・・・・・! Load TSS of this ap ・・・・・ ltr ax ! load TSS ! Now we are ready to address as usual and execute normal ! kernel code, so, lets go ! Each CPU needs its own stack space inside kernel stack ! Make esp point to cpus stack top THIS_CPU(eax) SET_CPU_STK(eax) ! Enable AP cache call _enable_cache ! Continue in C code call _ap_main
  • トランポリンコードの処理
  • enable_cache()の概要• CPUのキャッシュを有効にします• CR0レジスタのCDとNWビットを0にします o CDビット:0にすることでキャッシュを有効化 o NWビット:0ならキャッシュヒット時にライトバックす る  486の場合はライトスルー 31 0 P C N P G D W E
  • enable_cache()の処理_enable_cache: mov ax, cr0 and ax, 0x9FFFFFFF ! 100111111111...111 mov cr0, ax wbinv
  • トランポリンコードの処理
  • ap_main()の処理概要• enable_cpu()を呼んでAPを有効にする• 次に動くプロセスを選ぶ o lock_pick_proc() o pick_proc()のロックを使う版• そのプロセスを動かす o restart() o restart()はminixに元々ある関数で、kernel/main..cのmain() 最後の処理でも使っている
  • ap_main()の処理/* This is the main routine for APs. This is the entry point before the CPU has been started and jumped to protected mode */ /* Tell BSP we are running */ ap_running_flag=AP_LIFE_FLAG_MARK; /* Now were ready to take some work. We find any task and call restart() to execute it (or to idle), but we must synchonize other cpus before enter kernel code */ lock_mp_kernel(); /* restart() will unlock later */
  • ap_main()の処理/* Enable APIC interrupt aceptance */enable_cpu(this_cpu,WITHOUT_ECHO);/* Now, kernel is our! */lock_pick_proc(); /* Is there any work? */restart(); /* Lets go... */
  • トランポリンコードの処理
  • enable_cpu()の処理概要• ap_main()から呼ばれた場合は、APの有効化をする• 今動いているCPUが有効化済みかチェック• 有効化しようとしているCPUがthis_cpuかチェック• 同じ場合 o enable_apic_ints()を呼んでAPCI・割り込みの有効化 o 次に動くプロセスの選択• 違う場合 o CPUに割り込みメッセージを送信
  • At last• これでSMPが完全に有効になりましたヽ(*´∀`)ノ キャッ ホーイ!!
  • Link• MultiProcessor Specification o http://www.intel.com/design/pentium/datashts/242016.HTM• Minix3 o http://www.minix3.org/• はてダ o http://d.hatena.ne.jp/masami256