void lapic::init() { klog_debug("Initialising Local APIC"); auto cpuid_res = cpuid(1); auto cpuid_apic_supported = (cpuid_res.edx & CPUID_FLAG_APIC) != 0; assertf(cpuid_apic_supported, "APIC not supported on this cpu!"); auto base_paddr = lapic_get_base_paddr(); auto base_vaddr = lapic_get_base_vaddr(); klog_debug("Local APIC base physical address is %x", base_paddr); klog_debug("Local APIC base virtual address is %x", base_vaddr); uint32_t version = lapic_get_version(base_vaddr); klog_debug("Local APIC version is %x", version); // hardware enable the local apic if it wasn't already enabled by setting its // base to what it was already (usually 0xfee00000) lapic_set_base_paddr(base_paddr); // clear task priority to enable all interrupts lapic_write_register(base_vaddr, LAPIC_TASK_PRIORITY_REG, 0); // set destination mode to flat, all cpus use logical id 1 lapic_write_register(base_vaddr, LAPIC_DESTINATION_FORMAT_REG, 0xffffffffu); lapic_write_register(base_vaddr, LAPIC_LOGICAL_DESTINATION_REG, 0x01000000u); // setup spurious interrupt vector register uint32_t flags = 0x100 | 0xff; lapic_write_register(base_vaddr, LAPIC_SPURIOUS_INTERRUPT_VECTOR_REG, flags); // initialise local apic timer lapic_init_timer(base_vaddr); }
/* * Check, whether this is a modern or a first generation APIC */ static int modern_apic(void) { /* AMD systems use old APIC versions, so check the CPU */ if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD && boot_cpu_data.x86 >= 0xf) return 1; return lapic_get_version() >= 0x14; }
static int modern_apic(void) { if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD && boot_cpu_data.x86 >= 0xf) return 1; return lapic_get_version() >= 0x14; }
static inline int lapic_is_integrated(void) { #ifdef CONFIG_X86_64 return 1; #else return APIC_INTEGRATED(lapic_get_version()); #endif }
/* * Check, if the APIC is integrated or a seperate chip */ static inline int lapic_is_integrated(void) { return APIC_INTEGRATED(lapic_get_version()); }