X-Git-Url: https://scm.lunaixsky.com/lunaix-os.git/blobdiff_plain/287a5f7ae6a3bec3d679a5de394e915b56c7367d..b26d3165c52589d1f8de37bf0df27ad96f460f47:/lunaix-os/hal/apic.c diff --git a/lunaix-os/hal/apic.c b/lunaix-os/hal/apic.c index 30951ef..099fd50 100644 --- a/lunaix-os/hal/apic.c +++ b/lunaix-os/hal/apic.c @@ -13,13 +13,16 @@ #include #include -#include +#include +#include #include #include LOG_MODULE("APIC") +static volatile uintptr_t _apic_base; + void apic_setup_lvts(); @@ -31,58 +34,62 @@ apic_init() // Make sure the APIC is there // FUTURE: Use 8259 as fallback - assert_msg(cpu_has_apic(), "No APIC detected!"); + + // 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_APIC_BASE_MSR), "i"(IA32_APIC_ENABLE) - : "eax", "ecx", "edx" - ); + // 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 - uint32_t apic_id = apic_read_reg(APIC_IDR) >> 24; - uint32_t apic_ver = apic_read_reg(APIC_VER); + 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\n", - apic_id, - apic_ver & 0xff, - (apic_ver >> 16) & 0xff); + 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 + + // 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 - uint32_t spiv = apic_read_reg(APIC_SPIVR); + u32_t spiv = apic_read_reg(APIC_SPIVR); // install our handler for spurious interrupt. - spiv = (spiv & ~0xff) | APIC_SPIV_APIC_ENABLE | APIC_SPIV_IV; + 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) +#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) +#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() @@ -91,3 +98,21 @@ apic_setup_lvts() apic_write_reg(APIC_LVT_LINT1, LVT_ENTRY_LINT1); apic_write_reg(APIC_LVT_ERROR, LVT_ENTRY_ERROR(APIC_ERROR_IV)); } + +void +apic_done_servicing() +{ + *(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