Changes in kernel/arch/ia32/src/smp/apic.c [acc7ce4:84afc7b] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/arch/ia32/src/smp/apic.c
racc7ce4 r84afc7b 33 33 */ 34 34 35 #include < typedefs.h>35 #include <arch/types.h> 36 36 #include <arch/smp/apic.h> 37 37 #include <arch/smp/ap.h> … … 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 */ 74 volatile uint32_t *l_apic = (uint32_t *) UINT32_C(0xfee00000); 75 volatile uint32_t *io_apic = (uint32_t *) UINT32_C(0xfec00000); 71 */ 72 volatile uint32_t *l_apic = (uint32_t *) 0xfee00000; 73 volatile uint32_t *io_apic = (uint32_t *) 0xfec00000; 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; 179 161 eoi_function = l_apic_eoi; 180 irqs_info = "apic";181 162 182 163 /* … … 185 166 * Other interrupts will be forwarded to the lowest priority CPU. 186 167 */ 187 io_apic_disable_irqs(0xffff U);168 io_apic_disable_irqs(0xffff); 188 169 189 170 irq_initialize(&l_apic_timer_irq); … … 198 179 for (i = 0; i < IRQ_COUNT; i++) { 199 180 int pin; 200 181 201 182 if ((pin = smp_irq_to_pin(i)) != -1) 202 183 io_apic_change_ioredtbl((uint8_t) pin, DEST_ALL, (uint8_t) (IVT_IRQBASE + i), LOPRI); … … 206 187 * Ensure that io_apic has unique ID. 207 188 */ 208 io_apic_id_t idreg;209 210 189 idreg.value = io_apic_read(IOAPICID); 211 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 */ 212 191 for (i = 0; i < APIC_ID_COUNT; i++) { 213 192 if (!((1 << i) & apic_id_mask)) { … … 218 197 } 219 198 } 220 199 221 200 /* 222 201 * Configure the BSP's lapic. 223 202 */ 224 203 l_apic_init(); 225 l_apic_debug(); 226 227 bsp_l_apic = l_apic_id(); 204 205 l_apic_debug(); 228 206 } 229 207 … … 233 211 * 234 212 * @return 0 on error, 1 on success. 235 *236 213 */ 237 214 int apic_poll_errors(void) … … 255 232 if (esr.illegal_register_address) 256 233 printf("Illegal Register Address\n"); 257 234 258 235 return !esr.err_bitmap; 259 236 } … … 264 241 * 265 242 * @return 0 on failure, 1 on success. 266 *267 243 */ 268 244 int l_apic_broadcast_custom_ipi(uint8_t vector) 269 245 { 270 246 icr_t icr; 271 247 272 248 icr.lo = l_apic[ICRlo]; 273 249 icr.delmod = DELMOD_FIXED; … … 277 253 icr.trigger_mode = TRIGMOD_LEVEL; 278 254 icr.vector = vector; 279 255 280 256 l_apic[ICRlo] = icr.lo; 281 257 282 258 icr.lo = l_apic[ICRlo]; 283 259 if (icr.delivs == DELIVS_PENDING) { … … 286 262 #endif 287 263 } 288 264 289 265 return apic_poll_errors(); 290 266 } … … 295 271 * 296 272 * @return 0 on failure, 1 on success. 297 *298 273 */ 299 274 int l_apic_send_init_ipi(uint8_t apicid) 300 275 { 276 icr_t icr; 277 int i; 278 301 279 /* 302 280 * Read the ICR register in and zero all non-reserved fields. 303 281 */ 304 icr_t icr;305 306 282 icr.lo = l_apic[ICRlo]; 307 283 icr.hi = l_apic[ICRhi]; … … 317 293 l_apic[ICRhi] = icr.hi; 318 294 l_apic[ICRlo] = icr.lo; 319 295 320 296 /* 321 297 * According to MP Specification, 20us should be enough to … … 323 299 */ 324 300 delay(20); 325 301 326 302 if (!apic_poll_errors()) 327 303 return 0; 328 304 329 305 icr.lo = l_apic[ICRlo]; 330 306 if (icr.delivs == DELIVS_PENDING) { … … 333 309 #endif 334 310 } 335 311 336 312 icr.delmod = DELMOD_INIT; 337 313 icr.destmod = DESTMOD_PHYS; … … 341 317 icr.vector = 0; 342 318 l_apic[ICRlo] = icr.lo; 343 319 344 320 /* 345 321 * Wait 10ms as MP Specification specifies. 346 322 */ 347 323 delay(10000); 348 324 349 325 if (!is_82489DX_apic(l_apic[LAVR])) { 350 326 /* 351 327 * If this is not 82489DX-based l_apic we must send two STARTUP IPI's. 352 328 */ 353 unsigned int i; 354 for (i = 0; i < 2; i++) { 329 for (i = 0; i<2; i++) { 355 330 icr.lo = l_apic[ICRlo]; 356 331 icr.vector = (uint8_t) (((uintptr_t) ap_boot) >> 12); /* calculate the reset vector */ … … 371 346 void l_apic_init(void) 372 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 373 359 /* Initialize LVT Error register. */ 374 lvt_error_t error;375 376 360 error.value = l_apic[LVT_Err]; 377 361 error.masked = true; 378 362 l_apic[LVT_Err] = error.value; 379 363 380 364 /* Initialize LVT LINT0 register. */ 381 lvt_lint_t lint;382 383 365 lint.value = l_apic[LVT_LINT0]; 384 366 lint.masked = true; 385 367 l_apic[LVT_LINT0] = lint.value; 386 368 387 369 /* Initialize LVT LINT1 register. */ 388 370 lint.value = l_apic[LVT_LINT1]; 389 371 lint.masked = true; 390 372 l_apic[LVT_LINT1] = lint.value; 391 373 392 374 /* Task Priority Register initialization. */ 393 tpr_t tpr;394 395 375 tpr.value = l_apic[TPR]; 396 376 tpr.pri_sc = 0; … … 399 379 400 380 /* Spurious-Interrupt Vector Register initialization. */ 401 svr_t svr;402 403 381 svr.value = l_apic[SVR]; 404 382 svr.vector = VECTOR_APIC_SPUR; … … 406 384 svr.focus_checking = true; 407 385 l_apic[SVR] = svr.value; 408 386 409 387 if (CPU->arch.family >= 6) 410 388 enable_l_apic_in_msr(); 411 389 412 390 /* Interrupt Command Register initialization. */ 413 icr_t icr;414 415 391 icr.lo = l_apic[ICRlo]; 416 392 icr.delmod = DELMOD_INIT; … … 422 398 423 399 /* Timer Divide Configuration Register initialization. */ 424 tdcr_t tdcr;425 426 400 tdcr.value = l_apic[TDCR]; 427 401 tdcr.div_value = DIVIDE_1; 428 402 l_apic[TDCR] = tdcr.value; 429 403 430 404 /* Program local timer. */ 431 lvt_tm_t tm;432 433 405 tm.value = l_apic[LVT_Tm]; 434 406 tm.vector = VECTOR_CLK; … … 436 408 tm.masked = false; 437 409 l_apic[LVT_Tm] = tm.value; 438 410 439 411 /* 440 412 * Measure and configure the timer to generate timer 441 413 * interrupt with period 1s/HZ seconds. 442 414 */ 443 uint32_tt1 = l_apic[CCRT];415 t1 = l_apic[CCRT]; 444 416 l_apic[ICRT] = 0xffffffff; 445 446 while (l_apic[CCRT] == t1); 447 417 418 while (l_apic[CCRT] == t1) 419 ; 420 448 421 t1 = l_apic[CCRT]; 449 delay(1000000 /HZ);450 uint32_tt2 = l_apic[CCRT];451 452 l_apic[ICRT] = t1 -t2;422 delay(1000000/HZ); 423 t2 = l_apic[CCRT]; 424 425 l_apic[ICRT] = t1-t2; 453 426 454 427 /* Program Logical Destination Register. */ 455 ASSERT(CPU->id < 8); 456 ldr_t ldr; 457 428 ASSERT(CPU->id < 8) 458 429 ldr.value = l_apic[LDR]; 459 430 ldr.id = (uint8_t) (1 << CPU->id); … … 461 432 462 433 /* Program Destination Format Register for Flat mode. */ 463 dfr_t dfr;464 465 434 dfr.value = l_apic[DFR]; 466 435 dfr.model = MODEL_FLAT; … … 478 447 { 479 448 #ifdef LAPIC_VERBOSE 480 printf("LVT on cpu%u, LAPIC ID: %" PRIu8 "\n",481 CPU->id, l_apic_id());482 483 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 484 455 tm.value = l_apic[LVT_Tm]; 485 printf("LVT Tm: vector=%" PRIu8 ", %s, %s, %s\n", 486 tm.vector, delivs_str[tm.delivs], mask_str[tm.masked], 487 tm_mode_str[tm.mode]); 488 489 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]); 490 457 lint.value = l_apic[LVT_LINT0]; 491 printf("LVT LINT0: vector=%" PRIu8 ", %s, %s, %s, irr=%u, %s, %s\n", 492 tm.vector, delmod_str[lint.delmod], delivs_str[lint.delivs], 493 intpol_str[lint.intpol], lint.irr, trigmod_str[lint.trigger_mode], 494 mask_str[lint.masked]); 495 496 lint.value = l_apic[LVT_LINT1]; 497 printf("LVT LINT1: vector=%" PRIu8 ", %s, %s, %s, irr=%u, %s, %s\n", 498 tm.vector, delmod_str[lint.delmod], delivs_str[lint.delivs], 499 intpol_str[lint.intpol], lint.irr, trigmod_str[lint.trigger_mode], 500 mask_str[lint.masked]); 501 502 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]); 503 461 error.value = l_apic[LVT_Err]; 504 printf("LVT Err: vector=%" PRIu8 ", %s, %s\n", error.vector, 505 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]); 506 463 #endif 507 464 } 508 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 509 478 /** Read from IO APIC register. 510 479 * … … 512 481 * 513 482 * @return Content of the addressed IO APIC register. 514 *515 483 */ 516 484 uint32_t io_apic_read(uint8_t address) … … 527 495 * 528 496 * @param address IO APIC register address. 529 * @param val Content to be written to the addressed IO APIC register. 530 * 531 */ 532 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) 533 500 { 534 501 io_regsel_t regsel; … … 537 504 regsel.reg_addr = address; 538 505 io_apic[IOREGSEL] = regsel.value; 539 io_apic[IOWIN] = val;506 io_apic[IOWIN] = x; 540 507 } 541 508 542 509 /** Change some attributes of one item in I/O Redirection Table. 543 510 * 544 * @param pin 545 * @param dest 546 * @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. 547 514 * @param flags Flags. 548 * 549 */ 550 void io_apic_change_ioredtbl(uint8_t pin, uint8_t dest, uint8_t vec, 551 unsigned int flags) 552 { 553 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; 554 520 555 521 if (flags & LOPRI) 556 522 dlvr = DELMOD_LOWPRI; 557 else 558 dlvr = DELMOD_FIXED; 559 560 io_redirection_reg_t reg; 523 561 524 reg.lo = io_apic_read((uint8_t) (IOREDTBL + pin * 2)); 562 525 reg.hi = io_apic_read((uint8_t) (IOREDTBL + pin * 2 + 1)); … … 567 530 reg.intpol = POLARITY_HIGH; 568 531 reg.delmod = dlvr; 569 reg.intvec = v ec;570 532 reg.intvec = v; 533 571 534 io_apic_write((uint8_t) (IOREDTBL + pin * 2), reg.lo); 572 535 io_apic_write((uint8_t) (IOREDTBL + pin * 2 + 1), reg.hi); … … 576 539 * 577 540 * @param irqmask Bitmask of IRQs to be masked (0 = do not mask, 1 = mask). 578 *579 541 */ 580 542 void io_apic_disable_irqs(uint16_t irqmask) 581 543 { 544 io_redirection_reg_t reg; 582 545 unsigned int i; 546 int pin; 547 583 548 for (i = 0; i < 16; i++) { 584 549 if (irqmask & (1 << i)) { … … 587 552 * mapping for the respective IRQ number. 588 553 */ 589 intpin = smp_irq_to_pin(i);554 pin = smp_irq_to_pin(i); 590 555 if (pin != -1) { 591 io_redirection_reg_t reg;592 593 556 reg.lo = io_apic_read((uint8_t) (IOREDTBL + pin * 2)); 594 557 reg.masked = true; … … 603 566 * 604 567 * @param irqmask Bitmask of IRQs to be unmasked (0 = do not unmask, 1 = unmask). 605 *606 568 */ 607 569 void io_apic_enable_irqs(uint16_t irqmask) 608 570 { 609 571 unsigned int i; 572 int pin; 573 io_redirection_reg_t reg; 574 610 575 for (i = 0; i < 16; i++) { 611 576 if (irqmask & (1 << i)) { … … 614 579 * mapping for the respective IRQ number. 615 580 */ 616 intpin = smp_irq_to_pin(i);581 pin = smp_irq_to_pin(i); 617 582 if (pin != -1) { 618 io_redirection_reg_t reg;619 620 583 reg.lo = io_apic_read((uint8_t) (IOREDTBL + pin * 2)); 621 584 reg.masked = false;
Note:
See TracChangeset
for help on using the changeset viewer.