X-Git-Url: https://scm.lunaixsky.com/lunaix-os.git/blobdiff_plain/32b9a6d76790c73d3d2d36d9081a2581cc65d184..28c176b668c841a3b7fb093faccf0efa39257603:/lunaix-os/arch/i386/hal/apic.c diff --git a/lunaix-os/arch/i386/hal/apic.c b/lunaix-os/arch/i386/hal/apic.c deleted file mode 100644 index 4e2501f..0000000 --- a/lunaix-os/arch/i386/hal/apic.c +++ /dev/null @@ -1,124 +0,0 @@ -/** - * @file apic.c - * @author Lunaixsky - * @brief Abstraction for Advanced Programmable Interrupts Controller (APIC) - * @version 0.1 - * @date 2022-03-06 - * - * @copyright Copyright (c) 2022 - * - */ - -#include "sys/x86_isa.h" -#include - -#include "sys/apic.h" -#include - -#include -#include -#include - -#include "pic.h" - -LOG_MODULE("APIC") - -static volatile ptr_t _apic_base; - -void -apic_setup_lvts(); - -void -apic_init() -{ - // ensure that external interrupt is disabled - cpu_disable_interrupt(); - - // Make sure the APIC is there - // FUTURE: Use 8259 as fallback - - // FIXME apic abstraction as local interrupt controller - // assert_msg(cpu_has_apic(), "No APIC detected!"); - - // As we are going to use APIC, disable the old 8259 PIC - pic_disable(); - - _apic_base = (ptr_t)ioremap(__APIC_BASE_PADDR, 4096); - - // Hardware enable the APIC - // By setting bit 11 of IA32_APIC_BASE register - // Note: After this point, you can't disable then re-enable it until a - // reset (i.e., reboot) - asm volatile("movl %0, %%ecx\n" - "rdmsr\n" - "orl %1, %%eax\n" - "wrmsr\n" ::"i"(IA32_MSR_APIC_BASE), - "i"(IA32_APIC_ENABLE) - : "eax", "ecx", "edx"); - - // Print the basic information of our current local APIC - u32_t apic_id = apic_read_reg(APIC_IDR) >> 24; - u32_t apic_ver = apic_read_reg(APIC_VER); - - kprintf(KINFO "ID: %x, Version: %x, Max LVT: %u", - apic_id, - apic_ver & 0xff, - (apic_ver >> 16) & 0xff); - - // initialize the local vector table (LVT) - apic_setup_lvts(); - - // initialize priority registers - - // set the task priority to the lowest possible, so all external interrupts - // are acceptable - // Note, the lowest possible priority class is 2, not 0, 1, as they are - // reserved for internal interrupts (vector 0-31, and each p-class - // resposible for 16 vectors). See Intel Manual Vol. 3A, 10-29 - apic_write_reg(APIC_TPR, APIC_PRIORITY(2, 0)); - - // enable APIC - u32_t spiv = apic_read_reg(APIC_SPIVR); - - // install our handler for spurious interrupt. - spiv = (spiv & ~0xff) | APIC_SPIV_APIC_ENABLE | APIC_SPIV_IV; - apic_write_reg(APIC_SPIVR, spiv); -} - -#define LVT_ENTRY_LINT0(vector) (LVT_DELIVERY_FIXED | vector) - -// Pin LINT#1 is configured for relaying NMI, but we masked it here as I think -// it is too early for that -// LINT#1 *must* be edge trigged (Intel manual vol3. 10-14) -#define LVT_ENTRY_LINT1 (LVT_DELIVERY_NMI | LVT_MASKED | LVT_TRIGGER_EDGE) -#define LVT_ENTRY_ERROR(vector) (LVT_DELIVERY_FIXED | vector) - -void -apic_setup_lvts() -{ - apic_write_reg(APIC_LVT_LINT0, LVT_ENTRY_LINT0(APIC_LINT0_IV)); - apic_write_reg(APIC_LVT_LINT1, LVT_ENTRY_LINT1); - apic_write_reg(APIC_LVT_ERROR, LVT_ENTRY_ERROR(APIC_ERROR_IV)); -} - -void -apic_on_eoi(struct x86_intc* intc_ctx, cpu_t cpu, int iv) -{ - // for all external interrupts except the spurious interrupt - // this is required by Intel Manual Vol.3A, section 10.8.1 & 10.8.5 - if (iv >= IV_EX_BEGIN && iv != APIC_SPIV_IV) { - *(unsigned int*)(_apic_base + APIC_EOI) = 0; - } -} - -unsigned int -apic_read_reg(unsigned int reg) -{ - return *(unsigned int*)(_apic_base + (reg)); -} - -void -apic_write_reg(unsigned int reg, unsigned int val) -{ - *(unsigned int*)(_apic_base + reg) = val; -} \ No newline at end of file