読者です 読者をやめる 読者になる 読者になる

mp_start()を見ていく。関数についてるコメントからこいつは、MP Configuration tableを読み込んで、各cpuを起動させるということがわかる。

minix

調べているのはここにあるソース。
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の読み込みはここまで。