Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Minix smp

3,582 views

Published on

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

Published in: Technology
  • Sex in your area is here: ♥♥♥ http://bit.ly/36cXjBY ♥♥♥
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • Follow the link, new dating source: ❤❤❤ http://bit.ly/36cXjBY ❤❤❤
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here

Minix smp

  1. 1. MinixとSMP〜Minix SMPを読んでみる〜 @masami256
  2. 2. Agenda• Minix SMP?• Minix SMP初期化の流れ• トランポリンコード
  3. 3. Minix SMP?• Minix SMPはMinix2.0.0でSMPを実装 o 作者はJesús M. Álvarez Llorenteさん o プロジェクトのページはこちら  http://gsd.unex.es/projects/minixsmp/  ソースや論文(スペイン語)がダウンロード可能• 対象アーキテクチャはx86
  4. 4. 基本用語• 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 プロセッサ間の割り込み
  5. 5. Agenda• Minix SMP?• Minix SMP初期化の流れ• トランポリンコード
  6. 6. SMPのセットアップ手順
  7. 7. SMPのセットアップ手順(続き)
  8. 8. 実際の流れを追いかけよう電源ON〜main()の間はSMPに関する処理はないので飛ばします
  9. 9. SMPのセットアップ手順
  10. 10. enable_cpu()の処理概要• main()から呼ばれた場合は、BSPの有効化をする• 今動いているCPU(this_cpu)が有効化済みかチェック• 有効化しようとしているCPUがthis_cpuかチェック• 同じ場合 o enable_apic_ints()を呼んでAPCI・割り込みの有効化 o 次に動くプロセスの選択• 違う場合 o CPUに割り込みメッセージを送信
  11. 11. 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); }}
  12. 12. 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としています。
  13. 13. 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);
  14. 14. 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;}
  15. 15. SMPのセットアップ手順
  16. 16. mp_start()の処理概要• load_fps()〜free_trampoline()までの処理を順番に呼び出し• 関数の終了時点でAPが起動するようになる
  17. 17. 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); }
  18. 18. SMPのセットアップ手順
  19. 19. 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内)
  20. 20. 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 */};
  21. 21. fps構造体• fpsの先頭4バイトはシグネチャです o シグネチャは"_MP_"であることと規定されてます• OSがfpsを探すときはfpsが置かれているべきアドレスを起点 とします o そこから16バイトおきにメモリの内容を読み込みます• 読み込んだ16バイトの領域がfpsかは、シグネチャとチェッ クサムで確認します• チェックサムの確認はfpsの領域(16バイト)を1バイトずつ読 み込んで数値として足し算していき、結果が0ならOKとなり ます
  22. 22. 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 */
  23. 23. SMPのセットアップ手順
  24. 24. 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と同じく、シグネチャとチェックサム
  25. 25. 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
  26. 26. 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 */};
  27. 27. 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 */
  28. 28. SMPのセットアップ手順
  29. 29. 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実 装では特に使用せずに読み飛ばしています
  30. 30. 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 : ・・・ }}
  31. 31. 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 */};
  32. 32. Processor Entriesの処理概要• CPUが有効かチェックする• CPU FLAGSフィールド(ce_flags)を調べる o 大きさは1バイトで2種類(各1bit)のビットがあります o ENビットが0なら、このCPUは無効  無効の場合、このCPUは使用禁止 o BPビットが1なら、このCPUはBSP• CPUが有効かどうかのチェックは必須です
  33. 33. 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;
  34. 34. 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 */};
  35. 35. I/O APIC Entriesの処理概要• I/O APIC Entriesで見なければいけないところ o ENビット(1bit)  CPU EntriesのENビットと同じく、有効なら1 になる o I/O APIC ADDRESS  APICへ読み書きするときに使うアドレス
  36. 36. 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;
  37. 37. SMPのセットアップ手順
  38. 38. find_trampoline()の処理概要• メモリ上でトランポリンコードを置く場所を探します• トランポリンコード? o トランポリン(時々間接的なジャンプベクトルと呼ばれ る)は、割り込み処理ルーチン、I/Oルーチンなどを示しな がらアドレスを保持する記憶域です。 次に、実行は、す ぐにトランポリンに飛びついて、飛び出るか、または弾 んで、したがって、用語はトランポリンです。  http://wapedia.mobi/en/Trampoline_(computers)• トランポリンコードはAPの初期化時に必要です o x86系CPUはリアルモードで起動するので、プロテクト モードに移行したりといった処理がAPも必要です
  39. 39. find_trampoline()の処理概要• トランポリンコードのサイズを計算• トランポリンコードを置ける場所の探索• GDT、IDTをレジスタにコピー• トランポリンコードを見つかった場所にコピー• トランポリンコード中のマシン語コードの書き換え
  40. 40. 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:
  41. 41. 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だ!と説明が書いてあるので、 それに則ってます。
  42. 42. 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 */ }
  43. 43. 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
  44. 44. 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--; } }}
  45. 45. SMPのセットアップ手順
  46. 46. send_init_ipi()の処理概要• APを起動させる前にipiを初期化します• MPの仕様書「Appendix A System BIOS Programming Guidelines」と「Appendix B Operating System Programming Guidelines」あたりに詳しく書かれています
  47. 47. 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」と説明があります
  48. 48. 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に 書き込みます
  49. 49. 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();• しばらくデータの設定が続いてから、実際にデータを書き込 んでいきます
  50. 50. 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の初期化が終りです
  51. 51. SMPのセットアップ手順
  52. 52. send_startup_ipi()の処理概要• この関数は引数を2個受け取ります o trampoline_addrはトランポリンのアドレス o which_cpuは起動させたいcpu番号  this_cpuマクロで取得したcpu番号です• この関数でipiを有効にすることで、APが起動するようにな ります
  53. 53. 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 */
  54. 54. 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が起動します
  55. 55. 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");}
  56. 56. SMPのセットアップ手順
  57. 57. 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);}
  58. 58. Agenda• Minix SMP?• Minix SMP初期化の流れ• トランポリンコード
  59. 59. トランポリンコードの処理• トランポリンコードでは実際にどんなことをするのか? 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の関数を呼び出すまでが一連の処理です
  60. 60. トランポリンコードの処理
  61. 61. トランポリンコードの処理概要• リアルモードからプロテクトモードに移行し、次の処理に 進む o cs・dsレジスタの設定 o gdtr、idtrの設定 o プロテクトモード移行 o _trampolin_pmへセグメントジャンプ
  62. 62. トランポリンコード(データ定義).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
  63. 63. トランポリンコード(処理部)_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
  64. 64. トランポリンコードの処理
  65. 65. trampoline_pm()の処理概要• 各種レジスタの設定• TSSの設定 o Task State Segmentの略 o タスク状態の保存・復元に使用するデータ領域 o x86ではTSSを使ってタスクを切り替えることができる• スタックの設定• キャッシュの有効化• ap_main()のコール
  66. 66. 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
  67. 67. トランポリンコードの処理
  68. 68. enable_cache()の概要• CPUのキャッシュを有効にします• CR0レジスタのCDとNWビットを0にします o CDビット:0にすることでキャッシュを有効化 o NWビット:0ならキャッシュヒット時にライトバックす る  486の場合はライトスルー 31 0 P C N P G D W E
  69. 69. enable_cache()の処理_enable_cache: mov ax, cr0 and ax, 0x9FFFFFFF ! 100111111111...111 mov cr0, ax wbinv
  70. 70. トランポリンコードの処理
  71. 71. ap_main()の処理概要• enable_cpu()を呼んでAPを有効にする• 次に動くプロセスを選ぶ o lock_pick_proc() o pick_proc()のロックを使う版• そのプロセスを動かす o restart() o restart()はminixに元々ある関数で、kernel/main..cのmain() 最後の処理でも使っている
  72. 72. 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 */
  73. 73. 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... */
  74. 74. トランポリンコードの処理
  75. 75. enable_cpu()の処理概要• ap_main()から呼ばれた場合は、APの有効化をする• 今動いているCPUが有効化済みかチェック• 有効化しようとしているCPUがthis_cpuかチェック• 同じ場合 o enable_apic_ints()を呼んでAPCI・割り込みの有効化 o 次に動くプロセスの選択• 違う場合 o CPUに割り込みメッセージを送信
  76. 76. At last• これでSMPが完全に有効になりましたヽ(*´∀`)ノ キャッ ホーイ!!
  77. 77. 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

×