Changes in kernel/arch/ia32/src/smp/mps.c [d99c1d2:0a79ad9] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/arch/ia32/src/smp/mps.c
rd99c1d2 r0a79ad9 27 27 */ 28 28 29 /** @addtogroup ia32 29 /** @addtogroup ia32 30 30 * @{ 31 31 */ … … 52 52 */ 53 53 54 #define FS_SIGNATURE 0x5f504d5f 55 #define CT_SIGNATURE 0x504d4350 56 57 static int mps_fs_check(uint8_t *base); 58 static int mps_ct_check(void); 59 60 static int configure_via_ct(void); 61 static int configure_via_default(uint8_t n); 62 63 static int ct_processor_entry(struct __processor_entry *pr); 64 static void ct_bus_entry(struct __bus_entry *bus); 65 static void ct_io_apic_entry(struct __io_apic_entry *ioa); 66 static void ct_io_intr_entry(struct __io_intr_entry *iointr); 67 static void ct_l_intr_entry(struct __l_intr_entry *lintr); 68 69 static void ct_extended_entries(void); 54 #define FS_SIGNATURE 0x5f504d5f 55 #define CT_SIGNATURE 0x504d4350 70 56 71 57 static struct mps_fs *fs; 72 58 static struct mps_ct *ct; 73 59 74 struct __processor_entry *processor_entries = NULL; 75 struct __bus_entry *bus_entries = NULL; 76 struct __io_apic_entry *io_apic_entries = NULL; 77 struct __io_intr_entry *io_intr_entries = NULL; 78 struct __l_intr_entry *l_intr_entries = NULL; 79 80 unsigned int processor_entry_cnt = 0; 81 unsigned int bus_entry_cnt = 0; 82 unsigned int io_apic_entry_cnt = 0; 83 unsigned int io_intr_entry_cnt = 0; 84 unsigned int l_intr_entry_cnt = 0; 85 86 /* 87 * Implementation of IA-32 SMP configuration interface. 88 */ 89 static size_t get_cpu_count(void); 90 static bool is_cpu_enabled(size_t i); 91 static bool is_bsp(size_t i); 92 static uint8_t get_cpu_apic_id(size_t i); 93 static int mps_irq_to_pin(unsigned int irq); 94 60 static struct __processor_entry *processor_entries = NULL; 61 static struct __bus_entry *bus_entries = NULL; 62 static struct __io_apic_entry *io_apic_entries = NULL; 63 static struct __io_intr_entry *io_intr_entries = NULL; 64 static struct __l_intr_entry *l_intr_entries = NULL; 65 66 static size_t io_apic_cnt = 0; 67 68 static size_t processor_entry_cnt = 0; 69 static size_t bus_entry_cnt = 0; 70 static size_t io_apic_entry_cnt = 0; 71 static size_t io_intr_entry_cnt = 0; 72 static size_t l_intr_entry_cnt = 0; 73 74 static uint8_t mps_cpu_apic_id(size_t i) 75 { 76 ASSERT(i < processor_entry_cnt); 77 78 return processor_entries[i].l_apic_id; 79 } 80 81 static bool mps_cpu_enabled(size_t i) 82 { 83 ASSERT(i < processor_entry_cnt); 84 85 /* 86 * FIXME: The current local APIC driver limits usable 87 * CPU IDs to 8. 88 * 89 */ 90 if (i > 7) 91 return false; 92 93 return (bool) ((processor_entries[i].cpu_flags & 0x01) == 0x01); 94 } 95 96 static bool mps_cpu_bootstrap(size_t i) 97 { 98 ASSERT(i < processor_entry_cnt); 99 100 return (bool) ((processor_entries[i].cpu_flags & 0x02) == 0x02); 101 } 102 103 static int mps_irq_to_pin(unsigned int irq) 104 { 105 size_t i; 106 107 for (i = 0; i < io_intr_entry_cnt; i++) { 108 if (io_intr_entries[i].src_bus_irq == irq && 109 io_intr_entries[i].intr_type == 0) 110 return io_intr_entries[i].dst_io_apic_pin; 111 } 112 113 return -1; 114 } 115 116 /** Implementation of IA-32 SMP configuration interface. 117 * 118 */ 95 119 struct smp_config_operations mps_config_operations = { 96 .cpu_count = get_cpu_count, 97 .cpu_enabled = is_cpu_enabled, 98 .cpu_bootstrap = is_bsp, 99 .cpu_apic_id = get_cpu_apic_id, 120 .cpu_enabled = mps_cpu_enabled, 121 .cpu_bootstrap = mps_cpu_bootstrap, 122 .cpu_apic_id = mps_cpu_apic_id, 100 123 .irq_to_pin = mps_irq_to_pin 101 124 }; 102 125 103 size_t get_cpu_count(void) 104 { 105 return processor_entry_cnt; 106 } 107 108 bool is_cpu_enabled(size_t i) 109 { 110 ASSERT(i < processor_entry_cnt); 111 return (bool) ((processor_entries[i].cpu_flags & 0x01) == 0x01); 112 } 113 114 bool is_bsp(size_t i) 115 { 116 ASSERT(i < processor_entry_cnt); 117 return (bool) ((processor_entries[i].cpu_flags & 0x02) == 0x02); 118 } 119 120 uint8_t get_cpu_apic_id(size_t i) 121 { 122 ASSERT(i < processor_entry_cnt); 123 return processor_entries[i].l_apic_id; 124 } 125 126 127 /* 128 * Used to check the integrity of the MP Floating Structure. 129 */ 130 int mps_fs_check(uint8_t *base) 126 /** Check the integrity of the MP Floating Structure. 127 * 128 */ 129 static bool mps_fs_check(uint8_t *base) 131 130 { 132 131 unsigned int i; … … 136 135 sum = (uint8_t) (sum + base[i]); 137 136 138 return !sum;139 } 140 141 /* 142 * Used to check the integrity of the MP Configuration Table.143 */ 144 intmps_ct_check(void)137 return (sum == 0); 138 } 139 140 /** Check the integrity of the MP Configuration Table. 141 * 142 */ 143 static bool mps_ct_check(void) 145 144 { 146 145 uint8_t *base = (uint8_t *) ct; 147 146 uint8_t *ext = base + ct->base_table_length; 148 147 uint8_t sum; 149 int i;150 151 /* countthe checksum for the base table */152 for (i = 0, sum = 0; i < ct->base_table_length; i++)148 uint16_t i; 149 150 /* Compute the checksum for the base table */ 151 for (i = 0, sum = 0; i < ct->base_table_length; i++) 153 152 sum = (uint8_t) (sum + base[i]); 154 153 155 154 if (sum) 156 return 0;157 158 /* countthe checksum for the extended table */155 return false; 156 157 /* Compute the checksum for the extended table */ 159 158 for (i = 0, sum = 0; i < ct->ext_table_length; i++) 160 159 sum = (uint8_t) (sum + ext[i]); 161 162 return sum == ct->ext_table_checksum; 163 } 164 165 void mps_init(void) 166 { 167 uint8_t *addr[2] = { NULL, (uint8_t *) PA2KA(0xf0000) }; 168 unsigned int i, j, length[2] = { 1024, 64 * 1024 }; 169 170 160 161 return (sum == ct->ext_table_checksum); 162 } 163 164 static void ct_processor_entry(struct __processor_entry *pr) 165 { 171 166 /* 172 * Find MP Floating Pointer Structure 173 * 1a. search first 1K of EBDA 174 * 1b. if EBDA is undefined, search last 1K of base memory 175 * 2. search 64K starting at 0xf0000 167 * Ignore processors which are not marked enabled. 176 168 */ 177 178 addr[0] = (uint8_t *) PA2KA(ebda ? ebda : 639 * 1024); 179 for (i = 0; i < 2; i++) { 180 for (j = 0; j < length[i]; j += 16) { 181 if (*((uint32_t *) &addr[i][j]) == 182 FS_SIGNATURE && mps_fs_check(&addr[i][j])) { 183 fs = (struct mps_fs *) &addr[i][j]; 184 goto fs_found; 185 } 169 if ((pr->cpu_flags & (1 << 0)) == 0) 170 return; 171 172 apic_id_mask |= (1 << pr->l_apic_id); 173 } 174 175 static void ct_bus_entry(struct __bus_entry *bus __attribute__((unused))) 176 { 177 #ifdef MPSCT_VERBOSE 178 char buf[7]; 179 180 memcpy((void *) buf, (void *) bus->bus_type, 6); 181 buf[6] = 0; 182 183 printf("MPS: bus=%" PRIu8 " (%s)\n", bus->bus_id, buf); 184 #endif 185 } 186 187 static void ct_io_apic_entry(struct __io_apic_entry *ioa) 188 { 189 /* This I/O APIC is marked unusable */ 190 if ((ioa->io_apic_flags & 1) == 0) 191 return; 192 193 if (io_apic_cnt++ > 0) { 194 /* 195 * Multiple I/O APICs are currently not supported. 196 */ 197 return; 198 } 199 200 io_apic = (uint32_t *) (uintptr_t) ioa->io_apic; 201 } 202 203 static void ct_io_intr_entry(struct __io_intr_entry *iointr 204 __attribute__((unused))) 205 { 206 #ifdef MPSCT_VERBOSE 207 printf("MPS: "); 208 209 switch (iointr->intr_type) { 210 case 0: 211 printf("INT"); 212 break; 213 case 1: 214 printf("NMI"); 215 break; 216 case 2: 217 printf("SMI"); 218 break; 219 case 3: 220 printf("ExtINT"); 221 break; 222 } 223 224 printf(", "); 225 226 switch (iointr->poel & 3) { 227 case 0: 228 printf("bus-like"); 229 break; 230 case 1: 231 printf("active high"); 232 break; 233 case 2: 234 printf("reserved"); 235 break; 236 case 3: 237 printf("active low"); 238 break; 239 } 240 241 printf(", "); 242 243 switch ((iointr->poel >> 2) & 3) { 244 case 0: 245 printf("bus-like"); 246 break; 247 case 1: 248 printf("edge-triggered"); 249 break; 250 case 2: 251 printf("reserved"); 252 break; 253 case 3: 254 printf("level-triggered"); 255 break; 256 } 257 258 printf(", bus=%" PRIu8 " irq=%" PRIu8 " io_apic=%" PRIu8" pin=%" 259 PRIu8 "\n", iointr->src_bus_id, iointr->src_bus_irq, 260 iointr->dst_io_apic_id, iointr->dst_io_apic_pin); 261 #endif 262 } 263 264 static void ct_l_intr_entry(struct __l_intr_entry *lintr 265 __attribute__((unused))) 266 { 267 #ifdef MPSCT_VERBOSE 268 printf("MPS: "); 269 270 switch (lintr->intr_type) { 271 case 0: 272 printf("INT"); 273 break; 274 case 1: 275 printf("NMI"); 276 break; 277 case 2: 278 printf("SMI"); 279 break; 280 case 3: 281 printf("ExtINT"); 282 break; 283 } 284 285 printf(", "); 286 287 switch (lintr->poel & 3) { 288 case 0: 289 printf("bus-like"); 290 break; 291 case 1: 292 printf("active high"); 293 break; 294 case 2: 295 printf("reserved"); 296 break; 297 case 3: 298 printf("active low"); 299 break; 300 } 301 302 printf(", "); 303 304 switch ((lintr->poel >> 2) & 3) { 305 case 0: 306 printf("bus-like"); 307 break; 308 case 1: 309 printf("edge-triggered"); 310 break; 311 case 2: 312 printf("reserved"); 313 break; 314 case 3: 315 printf("level-triggered"); 316 break; 317 } 318 319 printf(", bus=%" PRIu8 " irq=%" PRIu8 " l_apic=%" PRIu8" pin=%" 320 PRIu8 "\n", lintr->src_bus_id, lintr->src_bus_irq, 321 lintr->dst_l_apic_id, lintr->dst_l_apic_pin); 322 #endif 323 } 324 325 static void ct_extended_entries(void) 326 { 327 uint8_t *ext = (uint8_t *) ct + ct->base_table_length; 328 uint8_t *cur; 329 330 for (cur = ext; cur < ext + ct->ext_table_length; 331 cur += cur[CT_EXT_ENTRY_LEN]) { 332 switch (cur[CT_EXT_ENTRY_TYPE]) { 333 default: 334 printf("MPS: Skipping MP Configuration Table extended " 335 "entry type %" PRIu8 "\n", cur[CT_EXT_ENTRY_TYPE]); 186 336 } 187 337 } 188 189 return; 190 191 fs_found: 192 printf("%p: MPS Floating Pointer Structure\n", fs); 193 194 if (fs->config_type == 0 && fs->configuration_table) { 195 if (fs->mpfib2 >> 7) { 196 printf("%s: PIC mode not supported\n", __func__); 197 return; 198 } 199 200 ct = (struct mps_ct *)PA2KA((uintptr_t)fs->configuration_table); 201 config.cpu_count = configure_via_ct(); 202 } 203 else 204 config.cpu_count = configure_via_default(fs->config_type); 205 206 return; 207 } 208 209 int configure_via_ct(void) 210 { 211 uint8_t *cur; 212 unsigned int i, cnt; 213 338 } 339 340 static void configure_via_ct(void) 341 { 214 342 if (ct->signature != CT_SIGNATURE) { 215 printf("%s: bad ct->signature\n", __func__); 216 return 1; 217 } 343 printf("MPS: Wrong ct->signature\n"); 344 return; 345 } 346 218 347 if (!mps_ct_check()) { 219 printf("%s: bad ct checksum\n", __func__); 220 return 1; 221 } 348 printf("MPS: Wrong ct checksum\n"); 349 return; 350 } 351 222 352 if (ct->oem_table) { 223 printf("%s: ct->oem_table not supported\n", __func__); 224 return 1; 225 } 226 227 l_apic = (uint32_t *)(uintptr_t)ct->l_apic; 228 229 cnt = 0; 230 cur = &ct->base_table[0]; 353 printf("MPS: ct->oem_table not supported\n"); 354 return; 355 } 356 357 l_apic = (uint32_t *) (uintptr_t) ct->l_apic; 358 359 uint8_t *cur = &ct->base_table[0]; 360 uint16_t i; 361 231 362 for (i = 0; i < ct->entry_count; i++) { 232 363 switch (*cur) { 233 /* Processor entry */ 234 case 0: 364 case 0: /* Processor entry */ 235 365 processor_entries = processor_entries ? 236 366 processor_entries : 237 367 (struct __processor_entry *) cur; 238 368 processor_entry_cnt++; 239 cnt += ct_processor_entry((struct __processor_entry *) 240 cur); 369 ct_processor_entry((struct __processor_entry *) cur); 241 370 cur += 20; 242 371 break; 243 244 /* Bus entry */ 245 case 1: 372 case 1: /* Bus entry */ 246 373 bus_entries = bus_entries ? 247 374 bus_entries : (struct __bus_entry *) cur; … … 250 377 cur += 8; 251 378 break; 252 253 /* I/O Apic */ 254 case 2: 379 case 2: /* I/O APIC */ 255 380 io_apic_entries = io_apic_entries ? 256 381 io_apic_entries : (struct __io_apic_entry *) cur; 257 382 io_apic_entry_cnt++; 258 383 ct_io_apic_entry((struct __io_apic_entry *) cur); 259 384 cur += 8; 260 385 break; 261 262 /* I/O Interrupt Assignment */ 263 case 3: 386 case 3: /* I/O Interrupt Assignment */ 264 387 io_intr_entries = io_intr_entries ? 265 388 io_intr_entries : (struct __io_intr_entry *) cur; … … 268 391 cur += 8; 269 392 break; 270 271 /* Local Interrupt Assignment */ 272 case 4: 393 case 4: /* Local Interrupt Assignment */ 273 394 l_intr_entries = l_intr_entries ? 274 395 l_intr_entries : (struct __l_intr_entry *) cur; … … 277 398 cur += 8; 278 399 break; 279 280 400 default: 281 401 /* 282 402 * Something is wrong. Fallback to UP mode. 283 403 */ 284 285 printf("%s: ct badness\n", __func__); 286 return 1; 404 printf("MPS: ct badness %" PRIu8 "\n", *cur); 405 return; 287 406 } 288 407 } … … 292 411 */ 293 412 ct_extended_entries(); 294 return cnt; 295 } 296 297 int configure_via_default(uint8_t n __attribute__((unused))) 413 } 414 415 static void configure_via_default(uint8_t n __attribute__((unused))) 298 416 { 299 417 /* 300 418 * Not yet implemented. 301 419 */ 302 printf("%s: not supported\n", __func__); 303 return 1; 304 } 305 306 307 int ct_processor_entry(struct __processor_entry *pr __attribute__((unused))) 308 { 420 printf("MPS: Default configuration not supported\n"); 421 } 422 423 void mps_init(void) 424 { 425 uint8_t *addr[2] = { NULL, (uint8_t *) PA2KA(0xf0000) }; 426 unsigned int i; 427 unsigned int j; 428 unsigned int length[2] = { 1024, 64 * 1024 }; 429 309 430 /* 310 * Ignore processors which are not marked enabled. 431 * Find MP Floating Pointer Structure 432 * 1a. search first 1K of EBDA 433 * 1b. if EBDA is undefined, search last 1K of base memory 434 * 2. search 64K starting at 0xf0000 311 435 */ 312 if ((pr->cpu_flags & (1 << 0)) == 0) 313 return 0; 314 315 apic_id_mask |= (1 << pr->l_apic_id); 316 return 1; 317 } 318 319 void ct_bus_entry(struct __bus_entry *bus __attribute__((unused))) 320 { 321 #ifdef MPSCT_VERBOSE 322 char buf[7]; 323 memcpy((void *) buf, (void *) bus->bus_type, 6); 324 buf[6] = 0; 325 printf("bus%d: %s\n", bus->bus_id, buf); 326 #endif 327 } 328 329 void ct_io_apic_entry(struct __io_apic_entry *ioa) 330 { 331 static unsigned int io_apic_count = 0; 332 333 /* this ioapic is marked unusable */ 334 if ((ioa->io_apic_flags & 1) == 0) 335 return; 336 337 if (io_apic_count++ > 0) { 338 /* 339 * Multiple IO APIC's are currently not supported. 340 */ 341 return; 342 } 343 344 io_apic = (uint32_t *)(uintptr_t)ioa->io_apic; 345 } 346 347 //#define MPSCT_VERBOSE 348 void ct_io_intr_entry(struct __io_intr_entry *iointr __attribute__((unused))) 349 { 350 #ifdef MPSCT_VERBOSE 351 switch (iointr->intr_type) { 352 case 0: 353 printf("INT"); 354 break; 355 case 1: 356 printf("NMI"); 357 break; 358 case 2: 359 printf("SMI"); 360 break; 361 case 3: 362 printf("ExtINT"); 363 break; 364 } 365 putchar(','); 366 switch (iointr->poel & 3) { 367 case 0: 368 printf("bus-like"); 369 break; 370 case 1: 371 printf("active high"); 372 break; 373 case 2: 374 printf("reserved"); 375 break; 376 case 3: 377 printf("active low"); 378 break; 379 } 380 putchar(','); 381 switch ((iointr->poel >> 2) & 3) { 382 case 0: 383 printf("bus-like"); 384 break; 385 case 1: 386 printf("edge-triggered"); 387 break; 388 case 2: 389 printf("reserved"); 390 break; 391 case 3: 392 printf("level-triggered"); 393 break; 394 } 395 putchar(','); 396 printf("bus%d,irq%d", iointr->src_bus_id, iointr->src_bus_irq); 397 putchar(','); 398 printf("io_apic%d,pin%d", iointr->dst_io_apic_id, 399 iointr->dst_io_apic_pin); 400 putchar('\n'); 401 #endif 402 } 403 404 void ct_l_intr_entry(struct __l_intr_entry *lintr __attribute__((unused))) 405 { 406 #ifdef MPSCT_VERBOSE 407 switch (lintr->intr_type) { 408 case 0: 409 printf("INT"); 410 break; 411 case 1: 412 printf("NMI"); 413 break; 414 case 2: 415 printf("SMI"); 416 break; 417 case 3: 418 printf("ExtINT"); 419 break; 420 } 421 putchar(','); 422 switch (lintr->poel & 3) { 423 case 0: 424 printf("bus-like"); 425 break; 426 case 1: 427 printf("active high"); 428 break; 429 case 2: 430 printf("reserved"); 431 break; 432 case 3: 433 printf("active low"); 434 break; 435 } 436 putchar(','); 437 switch ((lintr->poel >> 2) & 3) { 438 case 0: 439 printf("bus-like"); 440 break; 441 case 1: 442 printf("edge-triggered"); 443 break; 444 case 2: 445 printf("reserved"); 446 break; 447 case 3: 448 printf("level-triggered"); 449 break; 450 } 451 putchar(','); 452 printf("bus%d,irq%d", lintr->src_bus_id, lintr->src_bus_irq); 453 putchar(','); 454 printf("l_apic%d,pin%d", lintr->dst_l_apic_id, lintr->dst_l_apic_pin); 455 putchar('\n'); 456 #endif 457 } 458 459 void ct_extended_entries(void) 460 { 461 uint8_t *ext = (uint8_t *) ct + ct->base_table_length; 462 uint8_t *cur; 463 464 for (cur = ext; cur < ext + ct->ext_table_length; 465 cur += cur[CT_EXT_ENTRY_LEN]) { 466 switch (cur[CT_EXT_ENTRY_TYPE]) { 467 default: 468 printf("%p: skipping MP Configuration Table extended " 469 "entry type %d\n", cur, cur[CT_EXT_ENTRY_TYPE]); 470 break; 436 437 addr[0] = (uint8_t *) PA2KA(ebda ? ebda : 639 * 1024); 438 for (i = 0; i < 2; i++) { 439 for (j = 0; j < length[i]; j += 16) { 440 if ((*((uint32_t *) &addr[i][j]) == 441 FS_SIGNATURE) && (mps_fs_check(&addr[i][j]))) { 442 fs = (struct mps_fs *) &addr[i][j]; 443 goto fs_found; 444 } 471 445 } 472 446 } 473 } 474 475 int mps_irq_to_pin(unsigned int irq) 476 { 477 unsigned int i; 478 479 for (i = 0; i < io_intr_entry_cnt; i++) { 480 if (io_intr_entries[i].src_bus_irq == irq && 481 io_intr_entries[i].intr_type == 0) 482 return io_intr_entries[i].dst_io_apic_pin; 483 } 484 485 return -1; 447 448 return; 449 450 fs_found: 451 printf("%p: MPS Floating Pointer Structure\n", fs); 452 453 if ((fs->config_type == 0) && (fs->configuration_table)) { 454 if (fs->mpfib2 >> 7) { 455 printf("MPS: PIC mode not supported\n"); 456 return; 457 } 458 459 ct = (struct mps_ct *) PA2KA((uintptr_t) fs->configuration_table); 460 configure_via_ct(); 461 } else 462 configure_via_default(fs->config_type); 463 464 if (processor_entry_cnt > 0) 465 config.cpu_count = processor_entry_cnt; 486 466 } 487 467
Note:
See TracChangeset
for help on using the changeset viewer.