1 /* 2 * APIC handling routines. APIC is a requirement for SMP 3 */ 4 #include <assert.h> 5 6 #include <unistd.h> 7 #include <minix/portio.h> 8 9 #include <minix/syslib.h> 10 #include <machine/cmos.h> 11 12 #include <minix/u64.h> 13 14 #include "apic.h" 15 #include "apic_asm.h" 16 #include "kernel/clock.h" 17 #include "glo.h" 18 #include "hw_intr.h" 19 20 #include "acpi.h" 21 22 #ifdef USE_WATCHDOG 23 #include "kernel/watchdog.h" 24 #endif 25 26 #define APIC_ENABLE 0x100 27 #define APIC_FOCUS_DISABLED (1 << 9) 28 #define APIC_SIV 0xFF 29 30 #define APIC_TDCR_2 0x00 31 #define APIC_TDCR_4 0x01 32 #define APIC_TDCR_8 0x02 33 #define APIC_TDCR_16 0x03 34 #define APIC_TDCR_32 0x08 35 #define APIC_TDCR_64 0x09 36 #define APIC_TDCR_128 0x0a 37 #define APIC_TDCR_1 0x0b 38 39 #define IS_SET(mask) (mask) 40 #define IS_CLEAR(mask) 0 41 42 #define APIC_LVTT_VECTOR_MASK 0x000000FF 43 #define APIC_LVTT_DS_PENDING (1 << 12) 44 #define APIC_LVTT_MASK (1 << 16) 45 #define APIC_LVTT_TM (1 << 17) 46 47 #define APIC_LVT_IIPP_MASK 0x00002000 48 #define APIC_LVT_IIPP_AH 0x00002000 49 #define APIC_LVT_IIPP_AL 0x00000000 50 51 #define APIC_LVT_TM_ONESHOT IS_CLEAR(APIC_LVTT_TM) 52 #define APIC_LVT_TM_PERIODIC IS_SET(APIC_LVTT_TM) 53 54 #define IOAPIC_REGSEL 0x0 55 #define IOAPIC_RW 0x10 56 57 #define APIC_ICR_DM_MASK 0x00000700 58 #define APIC_ICR_VECTOR APIC_LVTT_VECTOR_MASK 59 #define APIC_ICR_DM_FIXED (0 << 8) 60 #define APIC_ICR_DM_LOWEST_PRIORITY (1 << 8) 61 #define APIC_ICR_DM_SMI (2 << 8) 62 #define APIC_ICR_DM_RESERVED (3 << 8) 63 #define APIC_ICR_DM_NMI (4 << 8) 64 #define APIC_ICR_DM_INIT (5 << 8) 65 #define APIC_ICR_DM_STARTUP (6 << 8) 66 #define APIC_ICR_DM_EXTINT (7 << 8) 67 68 #define APIC_ICR_DM_PHYSICAL (0 << 11) 69 #define APIC_ICR_DM_LOGICAL (1 << 11) 70 71 #define APIC_ICR_DELIVERY_PENDING (1 << 12) 72 73 #define APIC_ICR_INT_POLARITY (1 << 13) 74 #define APIC_ICR_INTPOL_LOW IS_SET(APIC_ICR_INT_POLARITY) 75 #define APIC_ICR_INTPOL_HIGH IS_CLEAR(APIC_ICR_INT_POLARITY) 76 77 #define APIC_ICR_LEVEL_ASSERT (1 << 14) 78 #define APIC_ICR_LEVEL_DEASSERT (0 << 14) 79 80 #define APIC_ICR_TRIGGER (1 << 15) 81 #define APIC_ICR_TM_LEVEL IS_CLEAR(APIC_ICR_TRIGGER) 82 #define APIC_ICR_TM_EDGE IS_CLEAR(APIC_ICR_TRIGGER) 83 84 #define APIC_ICR_INT_MASK (1 << 16) 85 86 #define APIC_ICR_DEST_FIELD (0 << 18) 87 #define APIC_ICR_DEST_SELF (1 << 18) 88 #define APIC_ICR_DEST_ALL (2 << 18) 89 #define APIC_ICR_DEST_ALL_BUT_SELF (3 << 18) 90 91 #define IA32_APIC_BASE 0x1b 92 #define IA32_APIC_BASE_ENABLE_BIT 11 93 94 /* FIXME we should spread the irqs across as many priority levels as possible 95 * due to buggy hw */ 96 #define LAPIC_VECTOR(irq) (IRQ0_VECTOR +(irq)) 97 98 #define IOAPIC_IRQ_STATE_MASKED 0x1 99 100 /* currently only 2 interrupt priority levels are used */ 101 #define SPL0 0x0 102 #define SPLHI 0xF 103 104 105 struct io_apic io_apic[MAX_NR_IOAPICS]; 106 unsigned nioapics; 107 108 struct irq; 109 typedef void (* eoi_method_t)(struct irq *); 110 111 struct irq { 112 struct io_apic * ioa; 113 unsigned pin; 114 unsigned vector; 115 eoi_method_t eoi; 116 unsigned state; 117 }; 118 119 static struct irq io_apic_irq[NR_IRQ_VECTORS]; 120 121 /* 122 * to make APIC work if SMP is not configured, we need to set the maximal number 123 * of CPUS to 1, cpuid to return 0 and the current cpu is always BSP 124 */ 125 #ifdef CONFIG_SMP 126 127 #include "kernel/smp.h" 128 129 #endif 130 131 #include "kernel/spinlock.h" 132 133 134 #define lapic_write_icr1(val) lapic_write(LAPIC_ICR1, val) 135 #define lapic_write_icr2(val) lapic_write(LAPIC_ICR2, val) 136 137 #define lapic_read_icr1(x) lapic_read(LAPIC_ICR1) 138 #define lapic_read_icr2(x) lapic_read(LAPIC_ICR2) 139 140 #define is_boot_apic(apicid) ((apicid) == bsp_lapic_id) 141 142 #define VERBOSE_APIC(x) x 143 144 int ioapic_enabled; 145 u32_t lapic_addr_vaddr; 146 vir_bytes lapic_addr; 147 vir_bytes lapic_eoi_addr; 148 int bsp_lapic_id; 149 150 static volatile unsigned probe_ticks; 151 static u64_t tsc0, tsc1; 152 static u32_t lapic_tctr0, lapic_tctr1; 153 154 static unsigned apic_imcrp; 155 static const unsigned nlints = 0; 156 157 void arch_eoi(void) 158 { 159 apic_eoi(); 160 } 161 162 /* 163 * FIXME this should be a cpulocal variable but there are some problems with 164 * arch specific cpulocals. As this variable is write-once-read-only it is ok to 165 * have at as an array until we resolve the cpulocals properly 166 */ 167 static u32_t lapic_bus_freq[CONFIG_MAX_CPUS]; 168 /* the probe period will be roughly 100ms */ 169 #define PROBE_TICKS (system_hz / 10) 170 171 #define IOAPIC_IOREGSEL 0x0 172 #define IOAPIC_IOWIN 0x10 173 174 static u32_t ioapic_read(u32_t ioa_base, u32_t reg) 175 { 176 *((volatile u32_t *)(ioa_base + IOAPIC_IOREGSEL)) = (reg & 0xff); 177 return *(volatile u32_t *)(ioa_base + IOAPIC_IOWIN); 178 } 179 180 static void ioapic_write(u32_t ioa_base, u8_t reg, u32_t val) 181 { 182 *((volatile u32_t *)(ioa_base + IOAPIC_IOREGSEL)) = reg; 183 *((volatile u32_t *)(ioa_base + IOAPIC_IOWIN)) = val; 184 } 185 186 void lapic_microsec_sleep(unsigned count); 187 void apic_idt_init(const int reset); 188 189 static void ioapic_enable_pin(vir_bytes ioapic_addr, int pin) 190 { 191 u32_t lo = ioapic_read(ioapic_addr, IOAPIC_REDIR_TABLE + pin * 2); 192 193 lo &= ~APIC_ICR_INT_MASK; 194 ioapic_write(ioapic_addr, IOAPIC_REDIR_TABLE + pin * 2, lo); 195 } 196 197 static void ioapic_disable_pin(vir_bytes ioapic_addr, int pin) 198 { 199 u32_t lo = ioapic_read(ioapic_addr, IOAPIC_REDIR_TABLE + pin * 2); 200 201 lo |= APIC_ICR_INT_MASK; 202 ioapic_write(ioapic_addr, IOAPIC_REDIR_TABLE + pin * 2, lo); 203 } 204 205 #if 0 206 static void ioapic_redirt_entry_read(void * ioapic_addr, 207 int entry, 208 u32_t *hi, 209 u32_t *lo) 210 { 211 *lo = ioapic_read((u32_t)ioapic_addr, (u8_t) (IOAPIC_REDIR_TABLE + entry * 2)); 212 *hi = ioapic_read((u32_t)ioapic_addr, (u8_t) (IOAPIC_REDIR_TABLE + entry * 2 + 1)); 213 214 } 215 #endif 216 217 static void ioapic_redirt_entry_write(void * ioapic_addr, 218 int entry, 219 u32_t hi, 220 u32_t lo) 221 { 222 #if 0 223 VERBOSE_APIC(printf("IO apic redir entry %3d " 224 "write 0x%08x 0x%08x\n", entry, hi, lo)); 225 #endif 226 ioapic_write((u32_t)ioapic_addr, (u8_t) (IOAPIC_REDIR_TABLE + entry * 2 + 1), hi); 227 ioapic_write((u32_t)ioapic_addr, (u8_t) (IOAPIC_REDIR_TABLE + entry * 2), lo); 228 } 229 230 #define apic_read_tmr_vector(vec) \ 231 lapic_read(LAPIC_TMR + 0x10 * ((vec) >> 5)) 232 233 #define apic_read_irr_vector(vec) \ 234 lapic_read(LAPIC_IRR + 0x10 * ((vec) >> 5)) 235 236 #define apic_read_isr_vector(vec) \ 237 lapic_read(LAPIC_ISR + 0x10 * ((vec) >> 5)) 238 239 #define lapic_test_delivery_val(val, vector) ((val) & (1 << ((vector) & 0x1f))) 240 241 static void ioapic_eoi_level(struct irq * irq) 242 { 243 reg_t tmr; 244 245 tmr = apic_read_tmr_vector(irq->vector); 246 apic_eoi(); 247 248 /* 249 * test if it was a level or edge triggered interrupt. If delivered as 250 * edge exec the workaround for broken chipsets 251 */ 252 if (!lapic_test_delivery_val(tmr, irq->vector)) { 253 int is_masked; 254 u32_t lo; 255 256 panic("EDGE instead of LEVEL!"); 257 258 lo = ioapic_read(irq->ioa->addr, 259 IOAPIC_REDIR_TABLE + irq->pin * 2); 260 261 is_masked = lo & APIC_ICR_INT_MASK; 262 263 /* set mask and edge */ 264 lo |= APIC_ICR_INT_MASK; 265 lo &= ~APIC_ICR_TRIGGER; 266 ioapic_write(irq->ioa->addr, 267 IOAPIC_REDIR_TABLE + irq->pin * 2, lo); 268 269 /* set back to level and restore the mask bit */ 270 lo = ioapic_read(irq->ioa->addr, 271 IOAPIC_REDIR_TABLE + irq->pin * 2); 272 273 lo |= APIC_ICR_TRIGGER; 274 if (is_masked) 275 lo |= APIC_ICR_INT_MASK; 276 else 277 lo &= ~APIC_ICR_INT_MASK; 278 ioapic_write(irq->ioa->addr, 279 IOAPIC_REDIR_TABLE + irq->pin * 2, lo); 280 } 281 } 282 283 static void ioapic_eoi_edge(__unused struct irq * irq) 284 { 285 apic_eoi(); 286 } 287 288 void ioapic_eoi(int irq) 289 { 290 if (ioapic_enabled) { 291 io_apic_irq[irq].eoi(&io_apic_irq[irq]); 292 } 293 else 294 irq_8259_eoi(irq); 295 } 296 297 void ioapic_set_id(u32_t addr, unsigned int id) 298 { 299 ioapic_write(addr, IOAPIC_ID, id << 24); 300 } 301 302 int ioapic_enable_all(void) 303 { 304 i8259_disable(); 305 306 if (apic_imcrp) { 307 /* Select IMCR and disconnect 8259s. */ 308 outb(0x22, 0x70); 309 outb(0x23, 0x01); 310 } 311 312 return ioapic_enabled = 1; 313 } 314 315 /* disables a single IO APIC */ 316 static void ioapic_disable(struct io_apic * ioapic) 317 { 318 unsigned p; 319 320 for (p = 0; p < io_apic->pins; p++) { 321 u32_t low_32, hi_32; 322 low_32 = ioapic_read((u32_t)ioapic->addr, 323 (uint8_t) (IOAPIC_REDIR_TABLE + p * 2)); 324 hi_32 = ioapic_read((u32_t)ioapic->addr, 325 (uint8_t) (IOAPIC_REDIR_TABLE + p * 2 + 1)); 326 327 if (!(low_32 & APIC_ICR_INT_MASK)) { 328 low_32 |= APIC_ICR_INT_MASK; 329 ioapic_write((u32_t)ioapic->addr, 330 (uint8_t) (IOAPIC_REDIR_TABLE + p * 2 + 1), hi_32); 331 ioapic_write((u32_t)ioapic->addr, 332 (uint8_t) (IOAPIC_REDIR_TABLE + p * 2), low_32); 333 } 334 } 335 } 336 337 /* disables all IO APICs */ 338 void ioapic_disable_all(void) 339 { 340 unsigned ioa; 341 if (!ioapic_enabled) 342 return; 343 344 for (ioa = 0 ; ioa < nioapics; ioa++) 345 ioapic_disable(&io_apic[ioa]); 346 347 ioapic_enabled = 0; /* io apic, disabled */ 348 349 /* Enable 8259 - write 0x00 in OCW1 master and slave. */ 350 if (apic_imcrp) { 351 outb(0x22, 0x70); 352 outb(0x23, 0x00); 353 } 354 355 lapic_microsec_sleep(200); /* to enable APIC to switch to PIC */ 356 357 apic_idt_init(TRUE); /* reset */ 358 idt_reload(); 359 } 360 361 static void ioapic_disable_irq(unsigned irq) 362 { 363 if(!(io_apic_irq[irq].ioa)) { 364 printf("ioapic_disable_irq: no ioa set for irq %d!\n", irq); 365 return; 366 } 367 368 assert(io_apic_irq[irq].ioa); 369 370 ioapic_disable_pin(io_apic_irq[irq].ioa->addr, io_apic_irq[irq].pin); 371 io_apic_irq[irq].state |= IOAPIC_IRQ_STATE_MASKED; 372 } 373 374 static void ioapic_enable_irq(unsigned irq) 375 { 376 if(!(io_apic_irq[irq].ioa)) { 377 printf("ioapic_enable_irq: no ioa set for irq %d!\n", irq); 378 return; 379 } 380 381 assert(io_apic_irq[irq].ioa); 382 383 ioapic_enable_pin(io_apic_irq[irq].ioa->addr, io_apic_irq[irq].pin); 384 io_apic_irq[irq].state &= ~IOAPIC_IRQ_STATE_MASKED; 385 } 386 387 void ioapic_unmask_irq(unsigned irq) 388 { 389 if (ioapic_enabled) 390 ioapic_enable_irq(irq); 391 else 392 /* FIXME unlikely */ 393 irq_8259_unmask(irq); 394 } 395 396 void ioapic_mask_irq(unsigned irq) 397 { 398 if (ioapic_enabled) 399 ioapic_disable_irq(irq); 400 else 401 /* FIXME unlikely */ 402 irq_8259_mask(irq); 403 } 404 405 unsigned int apicid(void) 406 { 407 return lapic_read(LAPIC_ID) >> 24; 408 } 409 410 static int calib_clk_handler(irq_hook_t * UNUSED(hook)) 411 { 412 u32_t tcrt; 413 u64_t tsc; 414 415 probe_ticks++; 416 read_tsc_64(&tsc); 417 tcrt = lapic_read(LAPIC_TIMER_CCR); 418 419 420 if (probe_ticks == 1) { 421 lapic_tctr0 = tcrt; 422 tsc0 = tsc; 423 } 424 else if (probe_ticks == PROBE_TICKS) { 425 lapic_tctr1 = tcrt; 426 tsc1 = tsc; 427 stop_8253A_timer(); 428 } 429 430 BKL_UNLOCK(); 431 return 1; 432 } 433 434 static int spurious_irq_handler(irq_hook_t * UNUSED(hook)) 435 { 436 /* 437 * Do nothing, only unlock the kernel so we do not deadlock! 438 */ 439 BKL_UNLOCK(); 440 return 1; 441 } 442 443 static void apic_calibrate_clocks(unsigned cpu) 444 { 445 u32_t lvtt, val, lapic_delta; 446 u64_t tsc_delta; 447 u64_t cpu_freq; 448 449 irq_hook_t calib_clk, spurious_irq; 450 451 BOOT_VERBOSE(printf("Calibrating clock\n")); 452 /* 453 * Set Initial count register to the highest value so it does not 454 * underflow during the testing period 455 * */ 456 val = 0xffffffff; 457 lapic_write (LAPIC_TIMER_ICR, val); 458 459 /* Set Current count register */ 460 val = 0; 461 lapic_write (LAPIC_TIMER_CCR, val); 462 463 lvtt = lapic_read(LAPIC_TIMER_DCR) & ~0x0b; 464 /* Set Divide configuration register to 1 */ 465 lvtt = APIC_TDCR_1; 466 lapic_write(LAPIC_TIMER_DCR, lvtt); 467 468 /* 469 * mask the APIC timer interrupt in the LVT Timer Register so that we 470 * don't get an interrupt upon underflow which we don't know how to 471 * handle right know. If underflow happens, the system will not continue 472 * as something is wrong with the clock IRQ 0 and we cannot calibrate 473 * the clock which mean that we cannot run processes 474 */ 475 lvtt = lapic_read (LAPIC_LVTTR); 476 lvtt |= APIC_LVTT_MASK; 477 lapic_write (LAPIC_LVTTR, lvtt); 478 479 /* set the probe, we use the legacy timer, IRQ 0 */ 480 put_irq_handler(&calib_clk, CLOCK_IRQ, calib_clk_handler); 481 482 /* 483 * A spurious interrupt may occur during the clock calibration. Since we 484 * do this calibration in kernel, we need a special handler which will 485 * leave the BKL unlocked like the clock handler. This is a corner case, 486 * boot time only situation 487 */ 488 put_irq_handler(&spurious_irq, SPURIOUS_IRQ, spurious_irq_handler); 489 490 /* set the PIC timer to get some time */ 491 init_8253A_timer(system_hz); 492 493 /* 494 * We must unlock BKL here as the in-kernel interrupt will lock it 495 * again. The handler will unlock it after it is done. This is 496 * absolutely safe as only the BSP is running. It is just a workaround a 497 * corner case for APIC timer calibration 498 */ 499 BKL_UNLOCK(); 500 intr_enable(); 501 502 /* loop for some time to get a sample */ 503 while(probe_ticks < PROBE_TICKS) { 504 intr_enable(); 505 } 506 507 intr_disable(); 508 BKL_LOCK(); 509 510 /* remove the probe */ 511 rm_irq_handler(&calib_clk); 512 rm_irq_handler(&spurious_irq); 513 514 lapic_delta = lapic_tctr0 - lapic_tctr1; 515 tsc_delta = tsc1 - tsc0; 516 517 lapic_bus_freq[cpuid] = system_hz * lapic_delta / (PROBE_TICKS - 1); 518 BOOT_VERBOSE(printf("APIC bus freq %u MHz\n", 519 lapic_bus_freq[cpuid] / 1000000)); 520 cpu_freq = (tsc_delta / (PROBE_TICKS - 1)) * make64(system_hz, 0); 521 cpu_set_freq(cpuid, cpu_freq); 522 cpu_info[cpuid].freq = (unsigned long)(cpu_freq / 1000000); 523 BOOT_VERBOSE(cpu_print_freq(cpuid)); 524 } 525 526 void lapic_set_timer_one_shot(const u32_t usec) 527 { 528 /* sleep in micro seconds */ 529 u32_t lvtt; 530 u32_t ticks_per_us; 531 const u8_t cpu = cpuid; 532 533 ticks_per_us = (lapic_bus_freq[cpu] / 1000000) * config_apic_timer_x; 534 535 lapic_write(LAPIC_TIMER_ICR, usec * ticks_per_us); 536 537 lvtt = APIC_TDCR_1; 538 lapic_write(LAPIC_TIMER_DCR, lvtt); 539 540 /* configure timer as one-shot */ 541 lvtt = APIC_TIMER_INT_VECTOR; 542 lapic_write(LAPIC_LVTTR, lvtt); 543 } 544 545 void lapic_set_timer_periodic(const unsigned freq) 546 { 547 /* sleep in micro seconds */ 548 u32_t lvtt; 549 u32_t lapic_ticks_per_clock_tick; 550 const u8_t cpu = cpuid; 551 552 lapic_ticks_per_clock_tick = (lapic_bus_freq[cpu] / freq) * config_apic_timer_x; 553 554 lvtt = APIC_TDCR_1; 555 lapic_write(LAPIC_TIMER_DCR, lvtt); 556 557 /* configure timer as periodic */ 558 lvtt = APIC_LVTT_TM | APIC_TIMER_INT_VECTOR; 559 lapic_write(LAPIC_LVTTR, lvtt); 560 561 lapic_write(LAPIC_TIMER_ICR, lapic_ticks_per_clock_tick); 562 } 563 564 void lapic_stop_timer(void) 565 { 566 u32_t lvtt; 567 lvtt = lapic_read(LAPIC_LVTTR); 568 lapic_write(LAPIC_LVTTR, lvtt | APIC_LVTT_MASK); 569 /* zero the current counter so it can be restarted again */ 570 lapic_write(LAPIC_TIMER_ICR, 0); 571 lapic_write(LAPIC_TIMER_CCR, 0); 572 } 573 574 void lapic_restart_timer(void) 575 { 576 /* restart the timer only if the counter reached zero, i.e. expired */ 577 if (lapic_read(LAPIC_TIMER_CCR) == 0) 578 lapic_set_timer_one_shot(1000000/system_hz); 579 } 580 581 void lapic_microsec_sleep(unsigned count) 582 { 583 lapic_set_timer_one_shot(count); 584 while (lapic_read(LAPIC_TIMER_CCR)) 585 arch_pause(); 586 } 587 588 static u32_t lapic_errstatus(void) 589 { 590 lapic_write(LAPIC_ESR, 0); 591 return lapic_read(LAPIC_ESR); 592 } 593 594 #ifdef CONFIG_SMP 595 static int lapic_disable_in_msr(void) 596 { 597 u32_t msr_hi, msr_lo; 598 599 ia32_msr_read(IA32_APIC_BASE, &msr_hi, &msr_lo); 600 601 msr_lo &= ~(1 << IA32_APIC_BASE_ENABLE_BIT); 602 ia32_msr_write(IA32_APIC_BASE, msr_hi, msr_lo); 603 604 return 1; 605 } 606 #endif /* CONFIG_SMP */ 607 608 void lapic_disable(void) 609 { 610 /* Disable current APIC and close interrupts from PIC */ 611 u32_t val; 612 613 if (!lapic_addr) 614 return; 615 616 #ifdef CONFIG_SMP 617 if (cpu_is_bsp(cpuid) && !apic_imcrp) 618 #endif 619 { 620 /* leave it enabled if imcr is not set */ 621 val = lapic_read(LAPIC_LINT0); 622 val &= ~(APIC_ICR_DM_MASK|APIC_ICR_INT_MASK); 623 val |= APIC_ICR_DM_EXTINT; /* ExtINT at LINT0 */ 624 lapic_write (LAPIC_LINT0, val); 625 return; 626 } 627 628 #ifdef CONFIG_SMP 629 val = lapic_read(LAPIC_LINT0) & 0xFFFE58FF; 630 val |= APIC_ICR_INT_MASK; 631 lapic_write (LAPIC_LINT0, val); 632 633 val = lapic_read(LAPIC_LINT1) & 0xFFFE58FF; 634 val |= APIC_ICR_INT_MASK; 635 lapic_write (LAPIC_LINT1, val); 636 637 val = lapic_read(LAPIC_SIVR) & 0xFFFFFF00; 638 val &= ~APIC_ENABLE; 639 lapic_write(LAPIC_SIVR, val); 640 641 lapic_disable_in_msr(); 642 #endif /* CONFIG_SMP */ 643 } 644 645 static int lapic_enable_in_msr(void) 646 { 647 u32_t msr_hi, msr_lo; 648 649 ia32_msr_read(IA32_APIC_BASE, &msr_hi, &msr_lo); 650 651 #if 0 652 u32_t addr; 653 /*FIXME this is a problem on AP */ 654 /* 655 * FIXME if the location is different (unlikely) then the one we expect, 656 * update it 657 */ 658 addr = (msr_lo >> 12) | ((msr_hi & 0xf) << 20); 659 if (addr != (lapic_addr >> 12)) { 660 if (msr_hi & 0xf) { 661 printf("ERROR : APIC address needs more then 32 bits\n"); 662 return 0; 663 } 664 lapic_addr = msr_lo & ~((1 << 12) - 1); 665 } 666 #endif 667 668 msr_lo |= (1 << IA32_APIC_BASE_ENABLE_BIT); 669 ia32_msr_write(IA32_APIC_BASE, msr_hi, msr_lo); 670 671 return 1; 672 } 673 674 int lapic_enable(unsigned cpu) 675 { 676 u32_t val, nlvt; 677 678 if (!lapic_addr) 679 return 0; 680 681 cpu_has_tsc = _cpufeature(_CPUF_I386_TSC); 682 if (!cpu_has_tsc) { 683 printf("CPU lacks timestamp counter, " 684 "cannot calibrate LAPIC timer\n"); 685 return 0; 686 } 687 688 if (!lapic_enable_in_msr()) 689 return 0; 690 691 /* set the highest priority for ever */ 692 lapic_write(LAPIC_TPR, 0x0); 693 694 lapic_eoi_addr = LAPIC_EOI; 695 /* clear error state register. */ 696 val = lapic_errstatus (); 697 698 /* Enable Local APIC and set the spurious vector to 0xff. */ 699 val = lapic_read(LAPIC_SIVR); 700 val |= APIC_ENABLE | APIC_SPURIOUS_INT_VECTOR; 701 val &= ~APIC_FOCUS_DISABLED; 702 lapic_write(LAPIC_SIVR, val); 703 (void) lapic_read(LAPIC_SIVR); 704 705 apic_eoi(); 706 707 /* Program Logical Destination Register. */ 708 val = lapic_read(LAPIC_LDR) & ~0xFF000000; 709 val |= (cpu & 0xFF) << 24; 710 lapic_write(LAPIC_LDR, val); 711 712 /* Program Destination Format Register for Flat mode. */ 713 val = lapic_read(LAPIC_DFR) | 0xF0000000; 714 lapic_write (LAPIC_DFR, val); 715 716 val = lapic_read (LAPIC_LVTER) & 0xFFFFFF00; 717 lapic_write (LAPIC_LVTER, val); 718 719 nlvt = (lapic_read(LAPIC_VERSION)>>16) & 0xFF; 720 721 if(nlvt >= 4) { 722 val = lapic_read(LAPIC_LVTTMR); 723 lapic_write(LAPIC_LVTTMR, val | APIC_ICR_INT_MASK); 724 } 725 726 if(nlvt >= 5) { 727 val = lapic_read(LAPIC_LVTPCR); 728 lapic_write(LAPIC_LVTPCR, val | APIC_ICR_INT_MASK); 729 } 730 731 /* setup TPR to allow all interrupts. */ 732 val = lapic_read (LAPIC_TPR); 733 /* accept all interrupts */ 734 lapic_write (LAPIC_TPR, val & ~0xFF); 735 736 (void) lapic_read (LAPIC_SIVR); 737 apic_eoi(); 738 739 apic_calibrate_clocks(cpu); 740 BOOT_VERBOSE(printf("APIC timer calibrated\n")); 741 742 return 1; 743 } 744 745 void apic_spurios_intr_handler(void) 746 { 747 static unsigned x; 748 749 x++; 750 if (x == 1 || (x % 100) == 0) 751 printf("WARNING spurious interrupt(s) %d on cpu %d\n", x, cpuid); 752 } 753 754 void apic_error_intr_handler(void) 755 { 756 static unsigned x; 757 758 x++; 759 if (x == 1 || (x % 100) == 0) 760 printf("WARNING apic error (0x%x) interrupt(s) %d on cpu %d\n", 761 lapic_errstatus(), x, cpuid); 762 } 763 764 static struct gate_table_s gate_table_ioapic[] = { 765 { apic_hwint0, LAPIC_VECTOR( 0), INTR_PRIVILEGE }, 766 { apic_hwint1, LAPIC_VECTOR( 1), INTR_PRIVILEGE }, 767 { apic_hwint2, LAPIC_VECTOR( 2), INTR_PRIVILEGE }, 768 { apic_hwint3, LAPIC_VECTOR( 3), INTR_PRIVILEGE }, 769 { apic_hwint4, LAPIC_VECTOR( 4), INTR_PRIVILEGE }, 770 { apic_hwint5, LAPIC_VECTOR( 5), INTR_PRIVILEGE }, 771 { apic_hwint6, LAPIC_VECTOR( 6), INTR_PRIVILEGE }, 772 { apic_hwint7, LAPIC_VECTOR( 7), INTR_PRIVILEGE }, 773 { apic_hwint8, LAPIC_VECTOR( 8), INTR_PRIVILEGE }, 774 { apic_hwint9, LAPIC_VECTOR( 9), INTR_PRIVILEGE }, 775 { apic_hwint10, LAPIC_VECTOR(10), INTR_PRIVILEGE }, 776 { apic_hwint11, LAPIC_VECTOR(11), INTR_PRIVILEGE }, 777 { apic_hwint12, LAPIC_VECTOR(12), INTR_PRIVILEGE }, 778 { apic_hwint13, LAPIC_VECTOR(13), INTR_PRIVILEGE }, 779 { apic_hwint14, LAPIC_VECTOR(14), INTR_PRIVILEGE }, 780 { apic_hwint15, LAPIC_VECTOR(15), INTR_PRIVILEGE }, 781 { apic_hwint16, LAPIC_VECTOR(16), INTR_PRIVILEGE }, 782 { apic_hwint17, LAPIC_VECTOR(17), INTR_PRIVILEGE }, 783 { apic_hwint18, LAPIC_VECTOR(18), INTR_PRIVILEGE }, 784 { apic_hwint19, LAPIC_VECTOR(19), INTR_PRIVILEGE }, 785 { apic_hwint20, LAPIC_VECTOR(20), INTR_PRIVILEGE }, 786 { apic_hwint21, LAPIC_VECTOR(21), INTR_PRIVILEGE }, 787 { apic_hwint22, LAPIC_VECTOR(22), INTR_PRIVILEGE }, 788 { apic_hwint23, LAPIC_VECTOR(23), INTR_PRIVILEGE }, 789 { apic_hwint24, LAPIC_VECTOR(24), INTR_PRIVILEGE }, 790 { apic_hwint25, LAPIC_VECTOR(25), INTR_PRIVILEGE }, 791 { apic_hwint26, LAPIC_VECTOR(26), INTR_PRIVILEGE }, 792 { apic_hwint27, LAPIC_VECTOR(27), INTR_PRIVILEGE }, 793 { apic_hwint28, LAPIC_VECTOR(28), INTR_PRIVILEGE }, 794 { apic_hwint29, LAPIC_VECTOR(29), INTR_PRIVILEGE }, 795 { apic_hwint30, LAPIC_VECTOR(30), INTR_PRIVILEGE }, 796 { apic_hwint31, LAPIC_VECTOR(31), INTR_PRIVILEGE }, 797 { apic_hwint32, LAPIC_VECTOR(32), INTR_PRIVILEGE }, 798 { apic_hwint33, LAPIC_VECTOR(33), INTR_PRIVILEGE }, 799 { apic_hwint34, LAPIC_VECTOR(34), INTR_PRIVILEGE }, 800 { apic_hwint35, LAPIC_VECTOR(35), INTR_PRIVILEGE }, 801 { apic_hwint36, LAPIC_VECTOR(36), INTR_PRIVILEGE }, 802 { apic_hwint37, LAPIC_VECTOR(37), INTR_PRIVILEGE }, 803 { apic_hwint38, LAPIC_VECTOR(38), INTR_PRIVILEGE }, 804 { apic_hwint39, LAPIC_VECTOR(39), INTR_PRIVILEGE }, 805 { apic_hwint40, LAPIC_VECTOR(40), INTR_PRIVILEGE }, 806 { apic_hwint41, LAPIC_VECTOR(41), INTR_PRIVILEGE }, 807 { apic_hwint42, LAPIC_VECTOR(42), INTR_PRIVILEGE }, 808 { apic_hwint43, LAPIC_VECTOR(43), INTR_PRIVILEGE }, 809 { apic_hwint44, LAPIC_VECTOR(44), INTR_PRIVILEGE }, 810 { apic_hwint45, LAPIC_VECTOR(45), INTR_PRIVILEGE }, 811 { apic_hwint46, LAPIC_VECTOR(46), INTR_PRIVILEGE }, 812 { apic_hwint47, LAPIC_VECTOR(47), INTR_PRIVILEGE }, 813 { apic_hwint48, LAPIC_VECTOR(48), INTR_PRIVILEGE }, 814 { apic_hwint49, LAPIC_VECTOR(49), INTR_PRIVILEGE }, 815 { apic_hwint50, LAPIC_VECTOR(50), INTR_PRIVILEGE }, 816 { apic_hwint51, LAPIC_VECTOR(51), INTR_PRIVILEGE }, 817 { apic_hwint52, LAPIC_VECTOR(52), INTR_PRIVILEGE }, 818 { apic_hwint53, LAPIC_VECTOR(53), INTR_PRIVILEGE }, 819 { apic_hwint54, LAPIC_VECTOR(54), INTR_PRIVILEGE }, 820 { apic_hwint55, LAPIC_VECTOR(55), INTR_PRIVILEGE }, 821 { apic_hwint56, LAPIC_VECTOR(56), INTR_PRIVILEGE }, 822 { apic_hwint57, LAPIC_VECTOR(57), INTR_PRIVILEGE }, 823 { apic_hwint58, LAPIC_VECTOR(58), INTR_PRIVILEGE }, 824 { apic_hwint59, LAPIC_VECTOR(59), INTR_PRIVILEGE }, 825 { apic_hwint60, LAPIC_VECTOR(60), INTR_PRIVILEGE }, 826 { apic_hwint61, LAPIC_VECTOR(61), INTR_PRIVILEGE }, 827 { apic_hwint62, LAPIC_VECTOR(62), INTR_PRIVILEGE }, 828 { apic_hwint63, LAPIC_VECTOR(63), INTR_PRIVILEGE }, 829 { apic_spurios_intr, APIC_SPURIOUS_INT_VECTOR, INTR_PRIVILEGE }, 830 { apic_error_intr, APIC_ERROR_INT_VECTOR, INTR_PRIVILEGE }, 831 { NULL, 0, 0} 832 }; 833 834 static struct gate_table_s gate_table_common[] = { 835 { ipc_entry_softint_orig, IPC_VECTOR_ORIG, USER_PRIVILEGE }, 836 { kernel_call_entry_orig, KERN_CALL_VECTOR_ORIG, USER_PRIVILEGE }, 837 { ipc_entry_softint_um, IPC_VECTOR_UM, USER_PRIVILEGE }, 838 { kernel_call_entry_um, KERN_CALL_VECTOR_UM, USER_PRIVILEGE }, 839 { NULL, 0, 0} 840 }; 841 842 #ifdef CONFIG_SMP 843 static struct gate_table_s gate_table_smp[] = { 844 { apic_ipi_sched_intr, APIC_SMP_SCHED_PROC_VECTOR, INTR_PRIVILEGE }, 845 { apic_ipi_halt_intr, APIC_SMP_CPU_HALT_VECTOR, INTR_PRIVILEGE }, 846 { NULL, 0, 0} 847 }; 848 #endif 849 850 #ifdef APIC_DEBUG 851 static void lapic_set_dummy_handlers(void) 852 { 853 char * handler; 854 int vect = 32; /* skip the reserved vectors */ 855 856 handler = &lapic_intr_dummy_handles_start; 857 handler += vect * LAPIC_INTR_DUMMY_HANDLER_SIZE; 858 for(; handler < &lapic_intr_dummy_handles_end; 859 handler += LAPIC_INTR_DUMMY_HANDLER_SIZE) { 860 int_gate_idt(vect++, (vir_bytes) handler, 861 PRESENT | INT_GATE_TYPE | 862 (INTR_PRIVILEGE << DPL_SHIFT)); 863 } 864 } 865 #endif 866 867 /* Build descriptors for interrupt gates in IDT. */ 868 void apic_idt_init(const int reset) 869 { 870 u32_t val; 871 872 /* Set up idt tables for smp mode. 873 */ 874 int is_bsp; 875 876 if (reset) { 877 idt_copy_vectors_pic(); 878 idt_copy_vectors(gate_table_common); 879 return; 880 } 881 882 is_bsp = is_boot_apic(apicid()); 883 884 #ifdef APIC_DEBUG 885 if (is_bsp) 886 printf("APIC debugging is enabled\n"); 887 lapic_set_dummy_handlers(); 888 #endif 889 890 /* Build descriptors for interrupt gates in IDT. */ 891 if (ioapic_enabled) 892 idt_copy_vectors(gate_table_ioapic); 893 else 894 idt_copy_vectors_pic(); 895 896 idt_copy_vectors(gate_table_common); 897 898 #ifdef CONFIG_SMP 899 idt_copy_vectors(gate_table_smp); 900 #endif 901 902 /* Setup error interrupt vector */ 903 val = lapic_read(LAPIC_LVTER); 904 val |= APIC_ERROR_INT_VECTOR; 905 val &= ~ APIC_ICR_INT_MASK; 906 lapic_write(LAPIC_LVTER, val); 907 (void) lapic_read(LAPIC_LVTER); 908 909 /* configure the timer interupt handler */ 910 if (is_bsp) { 911 BOOT_VERBOSE(printf("Initiating APIC timer handler\n")); 912 /* register the timer interrupt handler for this CPU */ 913 int_gate_idt(APIC_TIMER_INT_VECTOR, (vir_bytes) lapic_timer_int_handler, 914 PRESENT | INT_GATE_TYPE | (INTR_PRIVILEGE << DPL_SHIFT)); 915 } 916 917 } 918 919 static int acpi_get_ioapics(struct io_apic * ioa, unsigned * nioa, unsigned max) 920 { 921 unsigned n = 0; 922 struct acpi_madt_ioapic * acpi_ioa; 923 924 while (n < max) { 925 acpi_ioa = acpi_get_ioapic_next(); 926 if (acpi_ioa == NULL) 927 break; 928 929 assert(acpi_ioa->address); 930 931 ioa[n].id = acpi_ioa->id; 932 ioa[n].addr = acpi_ioa->address; 933 ioa[n].paddr = (phys_bytes) acpi_ioa->address; 934 ioa[n].gsi_base = acpi_ioa->global_int_base; 935 ioa[n].pins = ((ioapic_read(ioa[n].addr, 936 IOAPIC_VERSION) & 0xff0000) >> 16)+1; 937 printf("IO APIC idx %d id %d addr 0x%lx paddr 0x%lx pins %d\n", 938 n, acpi_ioa->id, ioa[n].addr, ioa[n].paddr, 939 ioa[n].pins); 940 n++; 941 } 942 943 *nioa = n; 944 return n; 945 } 946 947 int detect_ioapics(void) 948 { 949 int status; 950 951 if (machine.acpi_rsdp) { 952 status = acpi_get_ioapics(io_apic, &nioapics, MAX_NR_IOAPICS); 953 } else { 954 status = 0; 955 } 956 if (!status) { 957 /* try something different like MPS */ 958 } 959 960 return status; 961 } 962 963 #ifdef CONFIG_SMP 964 965 void apic_send_ipi(unsigned vector, unsigned cpu, int type) 966 { 967 u32_t icr1, icr2; 968 969 if (ncpus == 1) 970 /* no need of sending an IPI */ 971 return; 972 973 while (lapic_read_icr1() & APIC_ICR_DELIVERY_PENDING) 974 arch_pause(); 975 976 icr1 = lapic_read_icr1() & 0xFFF0F800; 977 icr2 = lapic_read_icr2() & 0xFFFFFF; 978 979 switch (type) { 980 case APIC_IPI_DEST: 981 if (!cpu_is_ready(cpu)) 982 return; 983 lapic_write_icr2(icr2 | (cpuid2apicid[cpu] << 24)); 984 lapic_write_icr1(icr1 | APIC_ICR_DEST_FIELD | vector); 985 break; 986 case APIC_IPI_SELF: 987 lapic_write_icr2(icr2); 988 lapic_write_icr1(icr1 | APIC_ICR_DEST_SELF | vector); 989 break; 990 case APIC_IPI_TO_ALL_BUT_SELF: 991 lapic_write_icr2(icr2); 992 lapic_write_icr1(icr1 | APIC_ICR_DEST_ALL_BUT_SELF | vector); 993 break; 994 case APIC_IPI_TO_ALL: 995 lapic_write_icr2(icr2); 996 lapic_write_icr1(icr1 | APIC_ICR_DEST_ALL | vector); 997 break; 998 default: 999 printf("WARNING : unknown send ipi type request\n"); 1000 } 1001 1002 } 1003 1004 int apic_send_startup_ipi(unsigned cpu, phys_bytes trampoline) 1005 { 1006 int timeout; 1007 u32_t errstatus = 0; 1008 int i; 1009 1010 /* INIT-SIPI-SIPI sequence */ 1011 1012 for (i = 0; i < 2; i++) { 1013 u32_t val; 1014 1015 /* clear err status */ 1016 lapic_errstatus(); 1017 1018 /* set target pe */ 1019 val = lapic_read(LAPIC_ICR2) & 0xFFFFFF; 1020 val |= cpuid2apicid[cpu] << 24; 1021 lapic_write(LAPIC_ICR2, val); 1022 1023 /* send SIPI */ 1024 val = lapic_read(LAPIC_ICR1) & 0xFFF32000; 1025 val |= APIC_ICR_LEVEL_ASSERT |APIC_ICR_DM_STARTUP; 1026 val |= (((u32_t)trampoline >> 12)&0xff); 1027 lapic_write(LAPIC_ICR1, val); 1028 1029 timeout = 1000; 1030 1031 /* wait for 200 micro-seconds*/ 1032 lapic_microsec_sleep (200); 1033 errstatus = 0; 1034 1035 while ((lapic_read(LAPIC_ICR1) & APIC_ICR_DELIVERY_PENDING) && 1036 !errstatus) { 1037 errstatus = lapic_errstatus(); 1038 timeout--; 1039 if (!timeout) break; 1040 } 1041 1042 /* skip this one and continue with another cpu */ 1043 if (errstatus) 1044 return -1; 1045 } 1046 1047 return 0; 1048 } 1049 1050 int apic_send_init_ipi(unsigned cpu, phys_bytes trampoline) 1051 { 1052 u32_t ptr, errstatus = 0; 1053 int timeout; 1054 1055 /* set the warm reset vector */ 1056 ptr = (u32_t)(trampoline & 0xF); 1057 phys_copy(0x467, vir2phys(&ptr), sizeof(u16_t )); 1058 ptr = (u32_t)(trampoline >> 4); 1059 phys_copy(0x469, vir2phys(&ptr), sizeof(u16_t )); 1060 1061 /* set shutdown code */ 1062 outb (RTC_INDEX, 0xF); 1063 outb (RTC_IO, 0xA); 1064 1065 /* clear error state register. */ 1066 (void) lapic_errstatus(); 1067 1068 /* assert INIT IPI , No Shorthand, destination mode : physical */ 1069 lapic_write(LAPIC_ICR2, (lapic_read (LAPIC_ICR2) & 0xFFFFFF) | 1070 (cpuid2apicid[cpu] << 24)); 1071 lapic_write(LAPIC_ICR1, (lapic_read (LAPIC_ICR1) & 0xFFF32000) | 1072 APIC_ICR_DM_INIT | APIC_ICR_TM_LEVEL | APIC_ICR_LEVEL_ASSERT); 1073 1074 timeout = 1000; 1075 1076 /* sleep for 200 micro-seconds */ 1077 lapic_microsec_sleep(200); 1078 1079 errstatus = 0; 1080 1081 while ((lapic_read(LAPIC_ICR1) & APIC_ICR_DELIVERY_PENDING) && !errstatus) { 1082 errstatus = lapic_errstatus(); 1083 timeout--; 1084 if (!timeout) break; 1085 } 1086 1087 if (errstatus) 1088 return -1; /* to continue with a new processor */ 1089 1090 /* clear error state register. */ 1091 lapic_errstatus(); 1092 1093 /* deassert INIT IPI , No Shorthand, destination mode : physical */ 1094 lapic_write(LAPIC_ICR2, (lapic_read (LAPIC_ICR2) & 0xFFFFFF) | 1095 (cpuid2apicid[cpu] << 24)); 1096 lapic_write(LAPIC_ICR1, (lapic_read (LAPIC_ICR1) & 0xFFF32000) | 1097 APIC_ICR_DEST_ALL | APIC_ICR_TM_LEVEL); 1098 1099 timeout = 1000; 1100 errstatus = 0; 1101 1102 /* sleep for 200 micro-seconds */ 1103 lapic_microsec_sleep(200); 1104 1105 while ((lapic_read(LAPIC_ICR1)&APIC_ICR_DELIVERY_PENDING) && !errstatus) { 1106 errstatus = lapic_errstatus(); 1107 timeout--; 1108 if(!timeout) break; 1109 } 1110 1111 if (errstatus) 1112 return -1; /* with the new processor */ 1113 1114 /* clear error state register. */ 1115 (void) lapic_errstatus(); 1116 1117 /* wait 10ms */ 1118 lapic_microsec_sleep (10000); 1119 1120 return 0; 1121 } 1122 #endif 1123 1124 #ifndef CONFIG_SMP 1125 int apic_single_cpu_init(void) 1126 { 1127 if (!cpu_feature_apic_on_chip()) 1128 return 0; 1129 1130 lapic_addr = LOCAL_APIC_DEF_ADDR; 1131 ioapic_enabled = 0; 1132 1133 if (!lapic_enable(0)) { 1134 lapic_addr = 0x0; 1135 return 0; 1136 } 1137 1138 bsp_lapic_id = apicid(); 1139 printf("Boot cpu apic id %d\n", bsp_lapic_id); 1140 1141 acpi_init(); 1142 1143 if (!detect_ioapics()) { 1144 lapic_disable(); 1145 lapic_addr = 0x0; 1146 return 0; 1147 } 1148 1149 ioapic_enable_all(); 1150 1151 if (ioapic_enabled) 1152 machine.apic_enabled = 1; 1153 1154 apic_idt_init(0); /* Not a reset ! */ 1155 idt_reload(); 1156 return 1; 1157 } 1158 #endif 1159 1160 static eoi_method_t set_eoi_method(unsigned irq) 1161 { 1162 /* 1163 * in APIC mode the lowest 16 IRQs are reserved for legacy (E)ISA edge 1164 * triggered interrupts. All the rest is for PCI level triggered 1165 * interrupts 1166 */ 1167 if (irq < 16) 1168 return ioapic_eoi_edge; 1169 else 1170 return ioapic_eoi_level; 1171 } 1172 1173 void set_irq_redir_low(unsigned irq, u32_t * low) 1174 { 1175 u32_t val = 0; 1176 1177 /* clear the polarity, trigger, mask and vector fields */ 1178 val &= ~(APIC_ICR_VECTOR | APIC_ICR_INT_MASK | 1179 APIC_ICR_TRIGGER | APIC_ICR_INT_POLARITY); 1180 1181 if (irq < 16) { 1182 /* ISA active-high */ 1183 val &= ~APIC_ICR_INT_POLARITY; 1184 /* ISA edge triggered */ 1185 val &= ~APIC_ICR_TRIGGER; 1186 } 1187 else { 1188 /* PCI active-low */ 1189 val |= APIC_ICR_INT_POLARITY; 1190 /* PCI level triggered */ 1191 val |= APIC_ICR_TRIGGER; 1192 } 1193 1194 val |= io_apic_irq[irq].vector; 1195 1196 *low = val; 1197 } 1198 1199 void ioapic_set_irq(unsigned irq) 1200 { 1201 unsigned ioa; 1202 1203 assert(irq < NR_IRQ_VECTORS); 1204 1205 /* shared irq, already set */ 1206 if (io_apic_irq[irq].ioa && io_apic_irq[irq].eoi) 1207 return; 1208 1209 assert(!io_apic_irq[irq].ioa || !io_apic_irq[irq].eoi); 1210 1211 for (ioa = 0; ioa < nioapics; ioa++) { 1212 if (io_apic[ioa].gsi_base <= irq && 1213 io_apic[ioa].gsi_base + 1214 io_apic[ioa].pins > irq) { 1215 u32_t hi_32, low_32; 1216 1217 io_apic_irq[irq].ioa = &io_apic[ioa]; 1218 io_apic_irq[irq].pin = irq - io_apic[ioa].gsi_base; 1219 io_apic_irq[irq].eoi = set_eoi_method(irq); 1220 io_apic_irq[irq].vector = LAPIC_VECTOR(irq); 1221 1222 set_irq_redir_low(irq, &low_32); 1223 /* 1224 * route the interrupts to the bsp by default 1225 */ 1226 hi_32 = bsp_lapic_id << 24; 1227 ioapic_redirt_entry_write((void *) io_apic[ioa].addr, 1228 io_apic_irq[irq].pin, hi_32, low_32); 1229 } 1230 } 1231 } 1232 1233 void ioapic_unset_irq(unsigned irq) 1234 { 1235 assert(irq < NR_IRQ_VECTORS); 1236 1237 ioapic_disable_irq(irq); 1238 io_apic_irq[irq].ioa = NULL; 1239 io_apic_irq[irq].eoi = NULL; 1240 } 1241 1242 void ioapic_reset_pic(void) 1243 { 1244 apic_idt_init(TRUE); /* reset */ 1245 idt_reload(); 1246 1247 /* Enable 8259 - write 0x00 in OCW1 1248 * master and slave. */ 1249 outb(0x22, 0x70); 1250 outb(0x23, 0x00); 1251 } 1252 1253 static void irq_lapic_status(int irq) 1254 { 1255 u32_t lo; 1256 reg_t tmr, irr, isr; 1257 int vector; 1258 struct irq * intr; 1259 1260 intr = &io_apic_irq[irq]; 1261 1262 if (!intr->ioa) 1263 return; 1264 1265 vector = LAPIC_VECTOR(irq); 1266 tmr = apic_read_tmr_vector(vector); 1267 irr = apic_read_irr_vector(vector); 1268 isr = apic_read_isr_vector(vector); 1269 1270 1271 if (lapic_test_delivery_val(isr, vector)) { 1272 printf("IRQ %d vec %d trigger %s irr %d isr %d\n", 1273 irq, vector, 1274 lapic_test_delivery_val(tmr, vector) ? 1275 "level" : "edge", 1276 lapic_test_delivery_val(irr, vector) ? 1 : 0, 1277 lapic_test_delivery_val(isr, vector) ? 1 : 0); 1278 } else { 1279 printf("IRQ %d vec %d irr %d\n", 1280 irq, vector, 1281 lapic_test_delivery_val(irr, vector) ? 1 : 0); 1282 } 1283 1284 lo = ioapic_read(intr->ioa->addr, 1285 IOAPIC_REDIR_TABLE + intr->pin * 2); 1286 printf("\tpin %2d vec 0x%02x ioa %d redir_lo 0x%08x %s\n", 1287 intr->pin, 1288 intr->vector, 1289 intr->ioa->id, 1290 lo, 1291 intr->state & IOAPIC_IRQ_STATE_MASKED ? 1292 "masked" : "unmasked"); 1293 } 1294 1295 void dump_apic_irq_state(void) 1296 { 1297 int irq; 1298 1299 printf("--- IRQs state dump ---\n"); 1300 for (irq = 0; irq < NR_IRQ_VECTORS; irq++) { 1301 irq_lapic_status(irq); 1302 } 1303 printf("--- all ---\n"); 1304 } 1305