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