00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00035 #ifdef CONFIG_SMP
00036
00037 #include <config.h>
00038 #include <print.h>
00039 #include <debug.h>
00040 #include <arch/smp/mps.h>
00041 #include <arch/smp/apic.h>
00042 #include <arch/smp/smp.h>
00043 #include <func.h>
00044 #include <arch/types.h>
00045 #include <typedefs.h>
00046 #include <cpu.h>
00047 #include <arch/asm.h>
00048 #include <arch/bios/bios.h>
00049 #include <mm/frame.h>
00050
00051
00052
00053
00054
00055 #define FS_SIGNATURE 0x5f504d5f
00056 #define CT_SIGNATURE 0x504d4350
00057
00058 int mps_fs_check(__u8 *base);
00059 int mps_ct_check(void);
00060
00061 int configure_via_ct(void);
00062 int configure_via_default(__u8 n);
00063
00064 int ct_processor_entry(struct __processor_entry *pr);
00065 void ct_bus_entry(struct __bus_entry *bus);
00066 void ct_io_apic_entry(struct __io_apic_entry *ioa);
00067 void ct_io_intr_entry(struct __io_intr_entry *iointr);
00068 void ct_l_intr_entry(struct __l_intr_entry *lintr);
00069
00070 void ct_extended_entries(void);
00071
00072 static struct mps_fs *fs;
00073 static struct mps_ct *ct;
00074
00075 struct __processor_entry *processor_entries = NULL;
00076 struct __bus_entry *bus_entries = NULL;
00077 struct __io_apic_entry *io_apic_entries = NULL;
00078 struct __io_intr_entry *io_intr_entries = NULL;
00079 struct __l_intr_entry *l_intr_entries = NULL;
00080
00081 int processor_entry_cnt = 0;
00082 int bus_entry_cnt = 0;
00083 int io_apic_entry_cnt = 0;
00084 int io_intr_entry_cnt = 0;
00085 int l_intr_entry_cnt = 0;
00086
00087 waitq_t ap_completion_wq;
00088
00089
00090
00091
00092 static count_t get_cpu_count(void);
00093 static bool is_cpu_enabled(index_t i);
00094 static bool is_bsp(index_t i);
00095 static __u8 get_cpu_apic_id(index_t i);
00096 static int mps_irq_to_pin(int irq);
00097
00098 struct smp_config_operations mps_config_operations = {
00099 .cpu_count = get_cpu_count,
00100 .cpu_enabled = is_cpu_enabled,
00101 .cpu_bootstrap = is_bsp,
00102 .cpu_apic_id = get_cpu_apic_id,
00103 .irq_to_pin = mps_irq_to_pin
00104 };
00105
00106 count_t get_cpu_count(void)
00107 {
00108 return processor_entry_cnt;
00109 }
00110
00111 bool is_cpu_enabled(index_t i)
00112 {
00113 ASSERT(i < processor_entry_cnt);
00114 return processor_entries[i].cpu_flags & 0x1;
00115 }
00116
00117 bool is_bsp(index_t i)
00118 {
00119 ASSERT(i < processor_entry_cnt);
00120 return processor_entries[i].cpu_flags & 0x2;
00121 }
00122
00123 __u8 get_cpu_apic_id(index_t i)
00124 {
00125 ASSERT(i < processor_entry_cnt);
00126 return processor_entries[i].l_apic_id;
00127 }
00128
00129
00130
00131
00132
00133 int mps_fs_check(__u8 *base)
00134 {
00135 int i;
00136 __u8 sum;
00137
00138 for (i = 0, sum = 0; i < 16; i++)
00139 sum += base[i];
00140
00141 return !sum;
00142 }
00143
00144
00145
00146
00147 int mps_ct_check(void)
00148 {
00149 __u8 *base = (__u8 *) ct;
00150 __u8 *ext = base + ct->base_table_length;
00151 __u8 sum;
00152 int i;
00153
00154
00155 for (i=0,sum=0; i < ct->base_table_length; i++)
00156 sum += base[i];
00157
00158 if (sum)
00159 return 0;
00160
00161
00162 for (i=0,sum=0; i < ct->ext_table_length; i++)
00163 sum += ext[i];
00164
00165 return sum == ct->ext_table_checksum;
00166 }
00167
00168 void mps_init(void)
00169 {
00170 __u8 *addr[2] = { NULL, (__u8 *) PA2KA(0xf0000) };
00171 int i, j, length[2] = { 1024, 64*1024 };
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181 addr[0] = (__u8 *) PA2KA(ebda ? ebda : 639 * 1024);
00182 for (i = 0; i < 2; i++) {
00183 for (j = 0; j < length[i]; j += 16) {
00184 if (*((__u32 *) &addr[i][j]) == FS_SIGNATURE && mps_fs_check(&addr[i][j])) {
00185 fs = (struct mps_fs *) &addr[i][j];
00186 goto fs_found;
00187 }
00188 }
00189 }
00190
00191 return;
00192
00193 fs_found:
00194 printf("%p: MPS Floating Pointer Structure\n", fs);
00195
00196 if (fs->config_type == 0 && fs->configuration_table) {
00197 if (fs->mpfib2 >> 7) {
00198 printf("%s: PIC mode not supported\n", __FUNCTION__);
00199 return;
00200 }
00201
00202 ct = (struct mps_ct *)PA2KA((__address)fs->configuration_table);
00203 config.cpu_count = configure_via_ct();
00204 }
00205 else
00206 config.cpu_count = configure_via_default(fs->config_type);
00207
00208 return;
00209 }
00210
00211 int configure_via_ct(void)
00212 {
00213 __u8 *cur;
00214 int i, cnt;
00215
00216 if (ct->signature != CT_SIGNATURE) {
00217 printf("%s: bad ct->signature\n", __FUNCTION__);
00218 return 1;
00219 }
00220 if (!mps_ct_check()) {
00221 printf("%s: bad ct checksum\n", __FUNCTION__);
00222 return 1;
00223 }
00224 if (ct->oem_table) {
00225 printf("%s: ct->oem_table not supported\n", __FUNCTION__);
00226 return 1;
00227 }
00228
00229 l_apic = (__u32 *)(__address)ct->l_apic;
00230
00231 cnt = 0;
00232 cur = &ct->base_table[0];
00233 for (i=0; i < ct->entry_count; i++) {
00234 switch (*cur) {
00235
00236 case 0:
00237 processor_entries = processor_entries ? processor_entries : (struct __processor_entry *) cur;
00238 processor_entry_cnt++;
00239 cnt += ct_processor_entry((struct __processor_entry *) cur);
00240 cur += 20;
00241 break;
00242
00243
00244 case 1:
00245 bus_entries = bus_entries ? bus_entries : (struct __bus_entry *) cur;
00246 bus_entry_cnt++;
00247 ct_bus_entry((struct __bus_entry *) cur);
00248 cur += 8;
00249 break;
00250
00251
00252 case 2:
00253 io_apic_entries = io_apic_entries ? io_apic_entries : (struct __io_apic_entry *) cur;
00254 io_apic_entry_cnt++;
00255 ct_io_apic_entry((struct __io_apic_entry *) cur);
00256 cur += 8;
00257 break;
00258
00259
00260 case 3:
00261 io_intr_entries = io_intr_entries ? io_intr_entries : (struct __io_intr_entry *) cur;
00262 io_intr_entry_cnt++;
00263 ct_io_intr_entry((struct __io_intr_entry *) cur);
00264 cur += 8;
00265 break;
00266
00267
00268 case 4:
00269 l_intr_entries = l_intr_entries ? l_intr_entries : (struct __l_intr_entry *) cur;
00270 l_intr_entry_cnt++;
00271 ct_l_intr_entry((struct __l_intr_entry *) cur);
00272 cur += 8;
00273 break;
00274
00275 default:
00276
00277
00278
00279
00280 printf("%s: ct badness\n", __FUNCTION__);
00281 return 1;
00282 }
00283 }
00284
00285
00286
00287
00288 ct_extended_entries();
00289 return cnt;
00290 }
00291
00292 int configure_via_default(__u8 n)
00293 {
00294
00295
00296
00297 printf("%s: not supported\n", __FUNCTION__);
00298 return 1;
00299 }
00300
00301
00302 int ct_processor_entry(struct __processor_entry *pr)
00303 {
00304
00305
00306
00307 if ((pr->cpu_flags & (1<<0)) == 0)
00308 return 0;
00309
00310 apic_id_mask |= (1<<pr->l_apic_id);
00311 return 1;
00312 }
00313
00314 void ct_bus_entry(struct __bus_entry *bus)
00315 {
00316 #ifdef MPSCT_VERBOSE
00317 char buf[7];
00318 memcpy((void *) buf, (void *) bus->bus_type, 6);
00319 buf[6] = 0;
00320 printf("bus%d: %s\n", bus->bus_id, buf);
00321 #endif
00322 }
00323
00324 void ct_io_apic_entry(struct __io_apic_entry *ioa)
00325 {
00326 static int io_apic_count = 0;
00327
00328
00329 if ((ioa->io_apic_flags & 1) == 0)
00330 return;
00331
00332 if (io_apic_count++ > 0) {
00333
00334
00335
00336 return;
00337 }
00338
00339 io_apic = (__u32 *)(__address)ioa->io_apic;
00340 }
00341
00342
00343 void ct_io_intr_entry(struct __io_intr_entry *iointr)
00344 {
00345 #ifdef MPSCT_VERBOSE
00346 switch (iointr->intr_type) {
00347 case 0: printf("INT"); break;
00348 case 1: printf("NMI"); break;
00349 case 2: printf("SMI"); break;
00350 case 3: printf("ExtINT"); break;
00351 }
00352 putchar(',');
00353 switch (iointr->poel&3) {
00354 case 0: printf("bus-like"); break;
00355 case 1: printf("active high"); break;
00356 case 2: printf("reserved"); break;
00357 case 3: printf("active low"); break;
00358 }
00359 putchar(',');
00360 switch ((iointr->poel>>2)&3) {
00361 case 0: printf("bus-like"); break;
00362 case 1: printf("edge-triggered"); break;
00363 case 2: printf("reserved"); break;
00364 case 3: printf("level-triggered"); break;
00365 }
00366 putchar(',');
00367 printf("bus%d,irq%d", iointr->src_bus_id, iointr->src_bus_irq);
00368 putchar(',');
00369 printf("io_apic%d,pin%d", iointr->dst_io_apic_id, iointr->dst_io_apic_pin);
00370 putchar('\n');
00371 #endif
00372 }
00373
00374 void ct_l_intr_entry(struct __l_intr_entry *lintr)
00375 {
00376 #ifdef MPSCT_VERBOSE
00377 switch (lintr->intr_type) {
00378 case 0: printf("INT"); break;
00379 case 1: printf("NMI"); break;
00380 case 2: printf("SMI"); break;
00381 case 3: printf("ExtINT"); break;
00382 }
00383 putchar(',');
00384 switch (lintr->poel&3) {
00385 case 0: printf("bus-like"); break;
00386 case 1: printf("active high"); break;
00387 case 2: printf("reserved"); break;
00388 case 3: printf("active low"); break;
00389 }
00390 putchar(',');
00391 switch ((lintr->poel>>2)&3) {
00392 case 0: printf("bus-like"); break;
00393 case 1: printf("edge-triggered"); break;
00394 case 2: printf("reserved"); break;
00395 case 3: printf("level-triggered"); break;
00396 }
00397 putchar(',');
00398 printf("bus%d,irq%d", lintr->src_bus_id, lintr->src_bus_irq);
00399 putchar(',');
00400 printf("l_apic%d,pin%d", lintr->dst_l_apic_id, lintr->dst_l_apic_pin);
00401 putchar('\n');
00402 #endif
00403 }
00404
00405 void ct_extended_entries(void)
00406 {
00407 __u8 *ext = (__u8 *) ct + ct->base_table_length;
00408 __u8 *cur;
00409
00410 for (cur = ext; cur < ext + ct->ext_table_length; cur += cur[CT_EXT_ENTRY_LEN]) {
00411 switch (cur[CT_EXT_ENTRY_TYPE]) {
00412 default:
00413 printf("%p: skipping MP Configuration Table extended entry type %d\n", cur, cur[CT_EXT_ENTRY_TYPE]);
00414 break;
00415 }
00416 }
00417 }
00418
00419 int mps_irq_to_pin(int irq)
00420 {
00421 int i;
00422
00423 for(i=0;i<io_intr_entry_cnt;i++) {
00424 if (io_intr_entries[i].src_bus_irq == irq && io_intr_entries[i].intr_type == 0)
00425 return io_intr_entries[i].dst_io_apic_pin;
00426 }
00427
00428 return -1;
00429 }
00430
00431 #endif
00432