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