* Map the local APIC and setup necessary interrupt vectors. */
| 492 | * Map the local APIC and setup necessary interrupt vectors. |
| 493 | */ |
| 494 | static void |
| 495 | native_lapic_init(vm_paddr_t addr) |
| 496 | { |
| 497 | #ifdef SMP |
| 498 | uint64_t r, r1, r2, rx; |
| 499 | #endif |
| 500 | uint32_t ver; |
| 501 | int i; |
| 502 | bool arat; |
| 503 | |
| 504 | /* |
| 505 | * Enable x2APIC mode if possible. Map the local APIC |
| 506 | * registers page. |
| 507 | * |
| 508 | * Keep the LAPIC registers page mapped uncached for x2APIC |
| 509 | * mode too, to have direct map page attribute set to |
| 510 | * uncached. This is needed to work around CPU errata present |
| 511 | * on all Intel processors. |
| 512 | */ |
| 513 | KASSERT(trunc_page(addr) == addr, |
| 514 | ("local APIC not aligned on a page boundary")); |
| 515 | lapic_paddr = addr; |
| 516 | lapic_map = pmap_mapdev(addr, PAGE_SIZE); |
| 517 | if (x2apic_mode) { |
| 518 | native_lapic_enable_x2apic(); |
| 519 | lapic_map = NULL; |
| 520 | } |
| 521 | |
| 522 | /* Setup the spurious interrupt handler. */ |
| 523 | setidt(APIC_SPURIOUS_INT, IDTVEC(spuriousint), SDT_APIC, SEL_KPL, |
| 524 | GSEL_APIC); |
| 525 | |
| 526 | /* Perform basic initialization of the BSP's local APIC. */ |
| 527 | lapic_enable(); |
| 528 | |
| 529 | /* Set BSP's per-CPU local APIC ID. */ |
| 530 | PCPU_SET(apic_id, lapic_id()); |
| 531 | |
| 532 | /* Local APIC timer interrupt. */ |
| 533 | setidt(APIC_TIMER_INT, pti ? IDTVEC(timerint_pti) : IDTVEC(timerint), |
| 534 | SDT_APIC, SEL_KPL, GSEL_APIC); |
| 535 | |
| 536 | /* Local APIC error interrupt. */ |
| 537 | setidt(APIC_ERROR_INT, pti ? IDTVEC(errorint_pti) : IDTVEC(errorint), |
| 538 | SDT_APIC, SEL_KPL, GSEL_APIC); |
| 539 | |
| 540 | /* XXX: Thermal interrupt */ |
| 541 | |
| 542 | /* Local APIC CMCI. */ |
| 543 | setidt(APIC_CMC_INT, pti ? IDTVEC(cmcint_pti) : IDTVEC(cmcint), |
| 544 | SDT_APIC, SEL_KPL, GSEL_APIC); |
| 545 | |
| 546 | if ((resource_int_value("apic", 0, "clock", &i) != 0 || i != 0)) { |
| 547 | /* Set if APIC timer runs in C3. */ |
| 548 | arat = (cpu_power_eax & CPUTPM1_ARAT); |
| 549 | |
| 550 | bzero(&lapic_et, sizeof(lapic_et)); |
| 551 | lapic_et.et_name = "LAPIC"; |
nothing calls this directly
no test coverage detected