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