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