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