Changes in kernel/arch/ia32/src/smp/apic.c [d99c1d2:99718a2e] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/arch/ia32/src/smp/apic.c
rd99c1d2 r99718a2e 53 53 * Advanced Programmable Interrupt Controller for SMP systems. 54 54 * Tested on: 55 * Bochs 2.0.2 - Bochs 2.2.6 with 2-8 CPUs 56 * Simics 2.0.28 - Simics 2.2.19 2-15 CPUs 57 * VMware Workstation 5.5 with 2 CPUs 58 * QEMU 0.8.0 with 2-15 CPUs 59 * ASUS P/I-P65UP5 + ASUS C-P55T2D REV. 1.41 with 2x 200Mhz Pentium CPUs 60 * ASUS PCH-DL with 2x 3000Mhz Pentium 4 Xeon (HT) CPUs 61 * MSI K7D Master-L with 2x 2100MHz Athlon MP CPUs 55 * Bochs 2.0.2 - Bochs 2.2.6 with 2-8 CPUs 56 * Simics 2.0.28 - Simics 2.2.19 2-15 CPUs 57 * VMware Workstation 5.5 with 2 CPUs 58 * QEMU 0.8.0 with 2-15 CPUs 59 * ASUS P/I-P65UP5 + ASUS C-P55T2D REV. 1.41 with 2x 200Mhz Pentium CPUs 60 * ASUS PCH-DL with 2x 3000Mhz Pentium 4 Xeon (HT) CPUs 61 * MSI K7D Master-L with 2x 2100MHz Athlon MP CPUs 62 * 62 63 */ 63 64 … … 69 70 * optimize the code too much and accesses to l_apic and io_apic, that must 70 71 * always be 32-bit, would use byte oriented instructions. 72 * 71 73 */ 72 74 volatile uint32_t *l_apic = (uint32_t *) 0xfee00000; … … 74 76 75 77 uint32_t apic_id_mask = 0; 78 uint8_t bsp_l_apic = 0; 79 76 80 static irq_t l_apic_timer_irq; 77 81 … … 79 83 80 84 #ifdef LAPIC_VERBOSE 81 static c har *delmod_str[] = {85 static const char *delmod_str[] = { 82 86 "Fixed", 83 87 "Lowest Priority", … … 90 94 }; 91 95 92 static c har *destmod_str[] = {96 static const char *destmod_str[] = { 93 97 "Physical", 94 98 "Logical" 95 99 }; 96 100 97 static c har *trigmod_str[] = {101 static const char *trigmod_str[] = { 98 102 "Edge", 99 103 "Level" 100 104 }; 101 105 102 static c har *mask_str[] = {106 static const char *mask_str[] = { 103 107 "Unmasked", 104 108 "Masked" 105 109 }; 106 110 107 static c har *delivs_str[] = {111 static const char *delivs_str[] = { 108 112 "Idle", 109 113 "Send Pending" 110 114 }; 111 115 112 static c har *tm_mode_str[] = {116 static const char *tm_mode_str[] = { 113 117 "One-shot", 114 118 "Periodic" 115 119 }; 116 120 117 static c har *intpol_str[] = {121 static const char *intpol_str[] = { 118 122 "Polarity High", 119 123 "Polarity Low" … … 123 127 /** APIC spurious interrupt handler. 124 128 * 125 * @param n Interrupt vector.129 * @param n Interrupt vector. 126 130 * @param istate Interrupted state. 127 */ 128 static void apic_spurious(int n __attribute__((unused)), istate_t *istate __attribute__((unused))) 131 * 132 */ 133 static void apic_spurious(unsigned int n __attribute__((unused)), 134 istate_t *istate __attribute__((unused))) 129 135 { 130 136 #ifdef CONFIG_DEBUG … … 145 151 * irq->lock so we just unlock it and then lock it again. 146 152 */ 147 spinlock_unlock(&irq->lock);153 irq_spinlock_unlock(&irq->lock, false); 148 154 clock(); 149 spinlock_lock(&irq->lock); 155 irq_spinlock_lock(&irq->lock, false); 156 } 157 158 /** Get Local APIC ID. 159 * 160 * @return Local APIC ID. 161 * 162 */ 163 static uint8_t l_apic_id(void) 164 { 165 l_apic_id_t idreg; 166 167 idreg.value = l_apic[L_APIC_ID]; 168 return idreg.apic_id; 150 169 } 151 170 … … 153 172 void apic_init(void) 154 173 { 155 io_apic_id_t idreg; 156 157 exc_register(VECTOR_APIC_SPUR, "apic_spurious", (iroutine) apic_spurious); 158 174 exc_register(VECTOR_APIC_SPUR, "apic_spurious", false, 175 (iroutine_t) apic_spurious); 176 159 177 enable_irqs_function = io_apic_enable_irqs; 160 178 disable_irqs_function = io_apic_disable_irqs; … … 179 197 for (i = 0; i < IRQ_COUNT; i++) { 180 198 int pin; 181 199 182 200 if ((pin = smp_irq_to_pin(i)) != -1) 183 201 io_apic_change_ioredtbl((uint8_t) pin, DEST_ALL, (uint8_t) (IVT_IRQBASE + i), LOPRI); … … 187 205 * Ensure that io_apic has unique ID. 188 206 */ 207 io_apic_id_t idreg; 208 189 209 idreg.value = io_apic_read(IOAPICID); 190 if ((1 << idreg.apic_id) & apic_id_mask) { /* see if IO APIC ID is used already */210 if ((1 << idreg.apic_id) & apic_id_mask) { /* See if IO APIC ID is used already */ 191 211 for (i = 0; i < APIC_ID_COUNT; i++) { 192 212 if (!((1 << i) & apic_id_mask)) { … … 197 217 } 198 218 } 199 219 200 220 /* 201 221 * Configure the BSP's lapic. 202 222 */ 203 223 l_apic_init(); 204 205 l_apic_debug(); 224 l_apic_debug(); 225 226 bsp_l_apic = l_apic_id(); 206 227 } 207 228 … … 211 232 * 212 233 * @return 0 on error, 1 on success. 234 * 213 235 */ 214 236 int apic_poll_errors(void) … … 232 254 if (esr.illegal_register_address) 233 255 printf("Illegal Register Address\n"); 234 256 235 257 return !esr.err_bitmap; 236 258 } … … 241 263 * 242 264 * @return 0 on failure, 1 on success. 265 * 243 266 */ 244 267 int l_apic_broadcast_custom_ipi(uint8_t vector) 245 268 { 246 269 icr_t icr; 247 270 248 271 icr.lo = l_apic[ICRlo]; 249 272 icr.delmod = DELMOD_FIXED; … … 253 276 icr.trigger_mode = TRIGMOD_LEVEL; 254 277 icr.vector = vector; 255 278 256 279 l_apic[ICRlo] = icr.lo; 257 280 258 281 icr.lo = l_apic[ICRlo]; 259 282 if (icr.delivs == DELIVS_PENDING) { … … 262 285 #endif 263 286 } 264 287 265 288 return apic_poll_errors(); 266 289 } … … 271 294 * 272 295 * @return 0 on failure, 1 on success. 296 * 273 297 */ 274 298 int l_apic_send_init_ipi(uint8_t apicid) 275 299 { 300 /* 301 * Read the ICR register in and zero all non-reserved fields. 302 */ 276 303 icr_t icr; 277 int i; 278 279 /* 280 * Read the ICR register in and zero all non-reserved fields. 281 */ 304 282 305 icr.lo = l_apic[ICRlo]; 283 306 icr.hi = l_apic[ICRhi]; … … 293 316 l_apic[ICRhi] = icr.hi; 294 317 l_apic[ICRlo] = icr.lo; 295 318 296 319 /* 297 320 * According to MP Specification, 20us should be enough to … … 299 322 */ 300 323 delay(20); 301 324 302 325 if (!apic_poll_errors()) 303 326 return 0; 304 327 305 328 icr.lo = l_apic[ICRlo]; 306 329 if (icr.delivs == DELIVS_PENDING) { … … 309 332 #endif 310 333 } 311 334 312 335 icr.delmod = DELMOD_INIT; 313 336 icr.destmod = DESTMOD_PHYS; … … 317 340 icr.vector = 0; 318 341 l_apic[ICRlo] = icr.lo; 319 342 320 343 /* 321 344 * Wait 10ms as MP Specification specifies. 322 345 */ 323 346 delay(10000); 324 347 325 348 if (!is_82489DX_apic(l_apic[LAVR])) { 326 349 /* 327 350 * If this is not 82489DX-based l_apic we must send two STARTUP IPI's. 328 351 */ 329 for (i = 0; i<2; i++) { 352 unsigned int i; 353 for (i = 0; i < 2; i++) { 330 354 icr.lo = l_apic[ICRlo]; 331 355 icr.vector = (uint8_t) (((uintptr_t) ap_boot) >> 12); /* calculate the reset vector */ … … 346 370 void l_apic_init(void) 347 371 { 372 /* Initialize LVT Error register. */ 348 373 lvt_error_t error; 349 lvt_lint_t lint; 350 tpr_t tpr; 351 svr_t svr; 352 icr_t icr; 353 tdcr_t tdcr; 354 lvt_tm_t tm; 355 ldr_t ldr; 356 dfr_t dfr; 357 uint32_t t1, t2; 358 359 /* Initialize LVT Error register. */ 374 360 375 error.value = l_apic[LVT_Err]; 361 376 error.masked = true; 362 377 l_apic[LVT_Err] = error.value; 363 378 364 379 /* Initialize LVT LINT0 register. */ 380 lvt_lint_t lint; 381 365 382 lint.value = l_apic[LVT_LINT0]; 366 383 lint.masked = true; 367 384 l_apic[LVT_LINT0] = lint.value; 368 385 369 386 /* Initialize LVT LINT1 register. */ 370 387 lint.value = l_apic[LVT_LINT1]; 371 388 lint.masked = true; 372 389 l_apic[LVT_LINT1] = lint.value; 373 390 374 391 /* Task Priority Register initialization. */ 392 tpr_t tpr; 393 375 394 tpr.value = l_apic[TPR]; 376 395 tpr.pri_sc = 0; … … 379 398 380 399 /* Spurious-Interrupt Vector Register initialization. */ 400 svr_t svr; 401 381 402 svr.value = l_apic[SVR]; 382 403 svr.vector = VECTOR_APIC_SPUR; … … 384 405 svr.focus_checking = true; 385 406 l_apic[SVR] = svr.value; 386 407 387 408 if (CPU->arch.family >= 6) 388 409 enable_l_apic_in_msr(); 389 410 390 411 /* Interrupt Command Register initialization. */ 412 icr_t icr; 413 391 414 icr.lo = l_apic[ICRlo]; 392 415 icr.delmod = DELMOD_INIT; … … 398 421 399 422 /* Timer Divide Configuration Register initialization. */ 423 tdcr_t tdcr; 424 400 425 tdcr.value = l_apic[TDCR]; 401 426 tdcr.div_value = DIVIDE_1; 402 427 l_apic[TDCR] = tdcr.value; 403 428 404 429 /* Program local timer. */ 430 lvt_tm_t tm; 431 405 432 tm.value = l_apic[LVT_Tm]; 406 433 tm.vector = VECTOR_CLK; … … 408 435 tm.masked = false; 409 436 l_apic[LVT_Tm] = tm.value; 410 437 411 438 /* 412 439 * Measure and configure the timer to generate timer 413 440 * interrupt with period 1s/HZ seconds. 414 441 */ 442 uint32_t t1 = l_apic[CCRT]; 443 l_apic[ICRT] = 0xffffffff; 444 445 while (l_apic[CCRT] == t1); 446 415 447 t1 = l_apic[CCRT]; 416 l_apic[ICRT] = 0xffffffff; 417 418 while (l_apic[CCRT] == t1) 419 ; 420 421 t1 = l_apic[CCRT]; 422 delay(1000000/HZ); 423 t2 = l_apic[CCRT]; 424 425 l_apic[ICRT] = t1-t2; 448 delay(1000000 / HZ); 449 uint32_t t2 = l_apic[CCRT]; 450 451 l_apic[ICRT] = t1 - t2; 426 452 427 453 /* Program Logical Destination Register. */ 428 ASSERT(CPU->id < 8) 454 ASSERT(CPU->id < 8); 455 ldr_t ldr; 456 429 457 ldr.value = l_apic[LDR]; 430 458 ldr.id = (uint8_t) (1 << CPU->id); … … 432 460 433 461 /* Program Destination Format Register for Flat mode. */ 462 dfr_t dfr; 463 434 464 dfr.value = l_apic[DFR]; 435 465 dfr.model = MODEL_FLAT; … … 447 477 { 448 478 #ifdef LAPIC_VERBOSE 479 printf("LVT on cpu%" PRIs ", LAPIC ID: %" PRIu8 "\n", 480 CPU->id, l_apic_id()); 481 449 482 lvt_tm_t tm; 483 tm.value = l_apic[LVT_Tm]; 484 printf("LVT Tm: vector=%" PRIu8 ", %s, %s, %s\n", 485 tm.vector, delivs_str[tm.delivs], mask_str[tm.masked], 486 tm_mode_str[tm.mode]); 487 450 488 lvt_lint_t lint; 451 lvt_error_t error;452 453 printf("LVT on cpu%d, LAPIC ID: %d\n", CPU->id, l_apic_id());454 455 tm.value = l_apic[LVT_Tm];456 printf("LVT Tm: vector=%hhd, %s, %s, %s\n", tm.vector, delivs_str[tm.delivs], mask_str[tm.masked], tm_mode_str[tm.mode]);457 489 lint.value = l_apic[LVT_LINT0]; 458 printf("LVT LINT0: vector=%hhd, %s, %s, %s, irr=%d, %s, %s\n", tm.vector, delmod_str[lint.delmod], delivs_str[lint.delivs], intpol_str[lint.intpol], lint.irr, trigmod_str[lint.trigger_mode], mask_str[lint.masked]); 459 lint.value = l_apic[LVT_LINT1]; 460 printf("LVT LINT1: vector=%hhd, %s, %s, %s, irr=%d, %s, %s\n", tm.vector, delmod_str[lint.delmod], delivs_str[lint.delivs], intpol_str[lint.intpol], lint.irr, trigmod_str[lint.trigger_mode], mask_str[lint.masked]); 490 printf("LVT LINT0: vector=%" PRIu8 ", %s, %s, %s, irr=%u, %s, %s\n", 491 tm.vector, delmod_str[lint.delmod], delivs_str[lint.delivs], 492 intpol_str[lint.intpol], lint.irr, trigmod_str[lint.trigger_mode], 493 mask_str[lint.masked]); 494 495 lint.value = l_apic[LVT_LINT1]; 496 printf("LVT LINT1: vector=%" PRIu8 ", %s, %s, %s, irr=%u, %s, %s\n", 497 tm.vector, delmod_str[lint.delmod], delivs_str[lint.delivs], 498 intpol_str[lint.intpol], lint.irr, trigmod_str[lint.trigger_mode], 499 mask_str[lint.masked]); 500 501 lvt_error_t error; 461 502 error.value = l_apic[LVT_Err]; 462 printf("LVT Err: vector=%hhd, %s, %s\n", error.vector, delivs_str[error.delivs], mask_str[error.masked]); 503 printf("LVT Err: vector=%" PRIu8 ", %s, %s\n", error.vector, 504 delivs_str[error.delivs], mask_str[error.masked]); 463 505 #endif 464 506 } 465 507 466 /** Get Local APIC ID.467 *468 * @return Local APIC ID.469 */470 uint8_t l_apic_id(void)471 {472 l_apic_id_t idreg;473 474 idreg.value = l_apic[L_APIC_ID];475 return idreg.apic_id;476 }477 478 508 /** Read from IO APIC register. 479 509 * … … 481 511 * 482 512 * @return Content of the addressed IO APIC register. 513 * 483 514 */ 484 515 uint32_t io_apic_read(uint8_t address) … … 495 526 * 496 527 * @param address IO APIC register address. 497 * @param x Content to be written to the addressed IO APIC register. 498 */ 499 void io_apic_write(uint8_t address, uint32_t x) 528 * @param val Content to be written to the addressed IO APIC register. 529 * 530 */ 531 void io_apic_write(uint8_t address, uint32_t val) 500 532 { 501 533 io_regsel_t regsel; … … 504 536 regsel.reg_addr = address; 505 537 io_apic[IOREGSEL] = regsel.value; 506 io_apic[IOWIN] = x;538 io_apic[IOWIN] = val; 507 539 } 508 540 509 541 /** Change some attributes of one item in I/O Redirection Table. 510 542 * 511 * @param pin IO APIC pin number.512 * @param dest Interrupt destination address.513 * @param v Interrupt vector to trigger.543 * @param pin IO APIC pin number. 544 * @param dest Interrupt destination address. 545 * @param vec Interrupt vector to trigger. 514 546 * @param flags Flags. 515 */ 516 void io_apic_change_ioredtbl(uint8_t pin, uint8_t dest, uint8_t v, int flags) 517 { 518 io_redirection_reg_t reg; 519 int dlvr = DELMOD_FIXED; 547 * 548 */ 549 void io_apic_change_ioredtbl(uint8_t pin, uint8_t dest, uint8_t vec, 550 unsigned int flags) 551 { 552 unsigned int dlvr; 520 553 521 554 if (flags & LOPRI) 522 555 dlvr = DELMOD_LOWPRI; 523 556 else 557 dlvr = DELMOD_FIXED; 558 559 io_redirection_reg_t reg; 524 560 reg.lo = io_apic_read((uint8_t) (IOREDTBL + pin * 2)); 525 561 reg.hi = io_apic_read((uint8_t) (IOREDTBL + pin * 2 + 1)); … … 530 566 reg.intpol = POLARITY_HIGH; 531 567 reg.delmod = dlvr; 532 reg.intvec = v ;533 568 reg.intvec = vec; 569 534 570 io_apic_write((uint8_t) (IOREDTBL + pin * 2), reg.lo); 535 571 io_apic_write((uint8_t) (IOREDTBL + pin * 2 + 1), reg.hi); … … 539 575 * 540 576 * @param irqmask Bitmask of IRQs to be masked (0 = do not mask, 1 = mask). 577 * 541 578 */ 542 579 void io_apic_disable_irqs(uint16_t irqmask) 543 580 { 544 io_redirection_reg_t reg;545 581 unsigned int i; 546 int pin;547 548 582 for (i = 0; i < 16; i++) { 549 583 if (irqmask & (1 << i)) { … … 552 586 * mapping for the respective IRQ number. 553 587 */ 554 pin = smp_irq_to_pin(i);588 int pin = smp_irq_to_pin(i); 555 589 if (pin != -1) { 590 io_redirection_reg_t reg; 591 556 592 reg.lo = io_apic_read((uint8_t) (IOREDTBL + pin * 2)); 557 593 reg.masked = true; … … 566 602 * 567 603 * @param irqmask Bitmask of IRQs to be unmasked (0 = do not unmask, 1 = unmask). 604 * 568 605 */ 569 606 void io_apic_enable_irqs(uint16_t irqmask) 570 607 { 571 608 unsigned int i; 572 int pin;573 io_redirection_reg_t reg;574 575 609 for (i = 0; i < 16; i++) { 576 610 if (irqmask & (1 << i)) { … … 579 613 * mapping for the respective IRQ number. 580 614 */ 581 pin = smp_irq_to_pin(i);615 int pin = smp_irq_to_pin(i); 582 616 if (pin != -1) { 617 io_redirection_reg_t reg; 618 583 619 reg.lo = io_apic_read((uint8_t) (IOREDTBL + pin * 2)); 584 620 reg.masked = false;
Note:
See TracChangeset
for help on using the changeset viewer.