boolean_t lapic_probe(void) { uint32_t lo; uint32_t hi; if (cpuid_features() & CPUID_FEATURE_APIC) return TRUE; if (cpuid_family() == 6 || cpuid_family() == 15) { /* * Mobile Pentiums: * There may be a local APIC which wasn't enabled by BIOS. * So we try to enable it explicitly. */ rdmsr(MSR_IA32_APIC_BASE, lo, hi); lo &= ~MSR_IA32_APIC_BASE_BASE; lo |= MSR_IA32_APIC_BASE_ENABLE | LAPIC_START; lo |= MSR_IA32_APIC_BASE_ENABLE; wrmsr(MSR_IA32_APIC_BASE, lo, hi); /* * Re-initialize cpu features info and re-check. */ cpuid_set_info(); if (cpuid_features() & CPUID_FEATURE_APIC) { printf("Local APIC discovered and enabled\n"); lapic_os_enabled = TRUE; lapic_interrupt_base = LAPIC_REDUCED_INTERRUPT_BASE; return TRUE; } } return FALSE; }
/* Farm an update out to all CPUs */ static void xcpu_update(void) { if (register_locks() != KERN_SUCCESS) return; /* Get all CPUs to perform the update */ mp_broadcast(cpu_update, NULL); /* Update the cpuid info */ cpuid_set_info(); }
void lapic_shutdown(void) { uint32_t lo; uint32_t hi; uint32_t value; /* Shutdown if local APIC was enabled by OS */ if (lapic_os_enabled == FALSE) return; mp_disable_preemption(); /* ExtINT: masked */ if (get_cpu_number() == master_cpu) { value = LAPIC_READ(LVT_LINT0); value |= LAPIC_LVT_MASKED; LAPIC_WRITE(LVT_LINT0, value); } /* Error: masked */ LAPIC_WRITE(LVT_ERROR, LAPIC_READ(LVT_ERROR) | LAPIC_LVT_MASKED); /* Timer: masked */ LAPIC_WRITE(LVT_TIMER, LAPIC_READ(LVT_TIMER) | LAPIC_LVT_MASKED); /* Perfmon: masked */ LAPIC_WRITE(LVT_PERFCNT, LAPIC_READ(LVT_PERFCNT) | LAPIC_LVT_MASKED); /* APIC software disabled */ LAPIC_WRITE(SVR, LAPIC_READ(SVR) & ~LAPIC_SVR_ENABLE); /* Bypass the APIC completely and update cpu features */ rdmsr(MSR_IA32_APIC_BASE, lo, hi); lo &= ~MSR_IA32_APIC_BASE_ENABLE; wrmsr(MSR_IA32_APIC_BASE, lo, hi); cpuid_set_info(); mp_enable_preemption(); }