調べているのはここにあるソース。
http://gsd.unex.es/projects/minixsmp/
void mp_start() { /* Load MP configuraton and wake up each CPU in the system */ u32_t trampoline_addr; int cpu; /* Start messaging to console */ MP_STATUS[0]=0; ADDS_MP_STATUS("IntelMP multiprocessor kernel support v" \ MP_RELEASE "." MP_VERSION "\n"); /* Try to load MP structures from memory */ if (load_fps()) { /*print_fps_info();*/ if (load_mph()) { /*print_mp_configuration();*/ local_apic_base=mph.mpch_apic_addr; process_mp_configuration(); /* Try to allocate the trampoline for APs to start */ if ((trampoline_addr=find_trampoline())) { /* Start each processor */ FOR_EACH_AP(cpu) { if (cpu!=1) milli_delay(100); ap_running_flag=0; send_init_ipi(trampoline_addr, cpu); send_startup_ipi(trampoline_addr, cpu); if (! AP_running()) { ADDS_MP_STATUS("\n\n*** WARNING! AP#"); ADDN_MP_STATUS(cpu,10,1); ADDS_MP_STATUS(" is not running ***\n\n"); } } free_trampoline(trampoline_addr); } else ADDS_MP_STATUS("MP ERROR!: Unable to allocate trampoline\n"); } } }
まず、最初するのはload_fps()をコールして、MP floating structure pointerを読み込むこと。
load_fps()の実装は
int load_fps(void) { /* Find and load a valid FPS structure. Retun nonzero on success */ unsigned addr; /* for the moment, scan the whole base memory, in 16-byte steps */ for (addr=0xF5B30; addr<0xFFFF0; addr+=0x10) { phys_copy ( addr , vir2phys(&fps) , sizeof(fps) ); if (test_fps_checksum(&fps)) { /*ADDS_MP_STATUS("MP floating pointer struct found at 0x"); ADDN_MP_STATUS(addr,16,0); ADDS_MP_STATUS("\n");*/ return 1; } } ADDS_MP_STATUS("MP scan FAILLED! MP config table not found in base memory\n"); return 0; }
メモリからfpsを探すときの開始アドレスは0xF5B30から16バイトおきに0xFFFF0まで探索する。
データの読み込みに使ってるfpsはmp.cにあるグローバル変数。
struct floating_pointer fps; /* Structures for loading configuration */
内容はこんな感じ。MPの仕様にあった形になっている。
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が本当に正しいか、シグネチャとチェックサムを確認して調べる。
チェックをするのはtest_fps_checksum()で0以外を返せば正しいfpsを読んだことになる。
int test_fps_checksum(struct floating_pointer *fps) { unsigned char *data, checksum; int i; /* Check in a FPS structure for a valid signature and checksum Return noncero on success */ /* 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 */ }
最初はシグネチャのチェックが入る。
/* fisrt look for signature */ for (i=0; i<4; i++) if (fps->fp_signature[i] != SIGN_FPS[i]) return 0;
SIGN_FPSの値は"_MP_"。これはMPの仕様ではシグネチャは"_MP_"と決まっているため。
fpsのfp_signatureフィールドの値を1バイトずつSIGN_FPSと比較する。
次はチェックサムの確認。
/* then calculate checksum*/ data=(unsigned char *)fps; checksum=0; for (i=0; i<sizeof (struct floating_pointer); i++) checksum+= data[i];
MPの仕様書にある説明を要約すると、「全てのバイトを足した結果は0になる」とあるので、それを実行しているのが上記ループ。
そして、チェックサムの確認結果を返す。
return (!checksum); /* checksum ok if sums 0 */
そして、load_fps()に戻って、
if (test_fps_checksum(&fps)) { /*ADDS_MP_STATUS("MP floating pointer struct found at 0x"); ADDN_MP_STATUS(addr,16,0); ADDS_MP_STATUS("\n");*/ return 1; }
fpsが見つかっていれば、1を返してmp_start()に戻り、load_mph()をコールする。
MP Floating Pointer Structureの読み込みはここまで。