diff options
author | Liav A <liavalb@gmail.com> | 2020-03-06 03:27:08 +0200 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2020-03-06 10:32:32 +0100 |
commit | c335c94242c061ddcebd3dcb72eb26eb89f7a321 (patch) | |
tree | b772de504b044eb8d9277b8801dabb25f4781754 | |
parent | a3fa40fc07e4c27e781839adfe55accddf567ee7 (diff) | |
download | serenity-c335c94242c061ddcebd3dcb72eb26eb89f7a321.zip |
Kernel: Simplify APIC::enable()
We install a SpuriousInterruptHandler when calling APIC::enable(),
and we don't enable local interrupts for now.
-rw-r--r-- | Kernel/Interrupts/APIC.cpp | 37 | ||||
-rw-r--r-- | Kernel/Interrupts/SpuriousInterruptHandler.h | 1 |
2 files changed, 19 insertions, 19 deletions
diff --git a/Kernel/Interrupts/APIC.cpp b/Kernel/Interrupts/APIC.cpp index b950c85acd..e08452f1a8 100644 --- a/Kernel/Interrupts/APIC.cpp +++ b/Kernel/Interrupts/APIC.cpp @@ -28,10 +28,11 @@ #include <AK/Types.h> #include <Kernel/Arch/i386/CPU.h> #include <Kernel/Interrupts/APIC.h> +#include <Kernel/Interrupts/SpuriousInterruptHandler.h> #include <Kernel/VM/MemoryManager.h> #include <LibBareMetal/IO.h> -#define IRQ_APIC_SPURIOUS 0x1f +#define IRQ_APIC_SPURIOUS 0x7f #define APIC_BASE_MSR 0x1b @@ -39,6 +40,7 @@ #define APIC_REG_LD 0xd0 #define APIC_REG_DF 0xe0 #define APIC_REG_SIV 0xf0 +#define APIC_REG_TPR 0x80 #define APIC_REG_ICR_LOW 0x300 #define APIC_REG_ICR_HIGH 0x310 #define APIC_REG_LVT_TIMER 0x320 @@ -50,13 +52,6 @@ namespace Kernel { -extern "C" void apic_spurious_interrupt_entry(); - -asm( - ".globl apic_spurious_interrupt_entry \n" - "apic_spurious_interrupt_entry: \n" - " iret\n"); - namespace APIC { class ICRReg { @@ -120,14 +115,14 @@ namespace APIC { static void write_register(u32 offset, u32 value) { auto lapic_region = MM.allocate_kernel_region(PhysicalAddress(page_base_of((u32)g_apic_base)), PAGE_SIZE, "LAPIC Write Access", Region::Access::Read | Region::Access::Write, false, true); - auto* lapic = (u32*)lapic_region->vaddr().offset(offset_in_page((u32)g_apic_base)).offset(offset).as_ptr(); + auto* lapic = (volatile u32*)lapic_region->vaddr().offset(offset_in_page((u32)g_apic_base)).offset(offset).as_ptr(); *lapic = value; } static u32 read_register(u32 offset) { auto lapic_region = MM.allocate_kernel_region(PhysicalAddress(page_base_of((u32)g_apic_base)), PAGE_SIZE, "LAPIC Read Access", Region::Access::Read, false, true); - auto* lapic = (u32*)lapic_region->vaddr().offset(offset_in_page((u32)g_apic_base)).offset(offset).as_ptr(); + auto* lapic = (volatile u32*)lapic_region->vaddr().offset(offset_in_page((u32)g_apic_base)).offset(offset).as_ptr(); return *lapic; } @@ -190,23 +185,27 @@ namespace APIC { { klog() << "Enabling local APIC for cpu #" << cpu; + // dummy read, apparently to avoid a bug in old CPUs. + read_register(APIC_REG_SIV); // set spurious interrupt vector - write_register(APIC_REG_SIV, read_register(APIC_REG_SIV) | 0x100); + write_register(APIC_REG_SIV, IRQ_APIC_SPURIOUS | 0x100); // local destination mode (flat mode) write_register(APIC_REG_DF, 0xf0000000); // set destination id (note that this limits it to 8 cpus) - write_register(APIC_REG_LD, (1 << cpu) << 24); + write_register(APIC_REG_LD, 0); + + SpuriousInterruptHandler::initialize(IRQ_APIC_SPURIOUS); - register_interrupt_handler(IRQ_APIC_SPURIOUS, apic_spurious_interrupt_entry); + write_register(APIC_REG_LVT_TIMER, APIC_LVT(0, 0) | APIC_LVT_MASKED); + write_register(APIC_REG_LVT_THERMAL, APIC_LVT(0, 0) | APIC_LVT_MASKED); + write_register(APIC_REG_LVT_PERFORMANCE_COUNTER, APIC_LVT(0, 0) | APIC_LVT_MASKED); + write_register(APIC_REG_LVT_LINT0, APIC_LVT(0, 7) | APIC_LVT_MASKED); + write_register(APIC_REG_LVT_LINT1, APIC_LVT(0, 0) | APIC_LVT_TRIGGER_LEVEL); + write_register(APIC_REG_LVT_ERR, APIC_LVT(0, 0) | APIC_LVT_MASKED); - write_register(APIC_REG_LVT_TIMER, APIC_LVT(0xff, 0) | APIC_LVT_MASKED); - write_register(APIC_REG_LVT_THERMAL, APIC_LVT(0xff, 0) | APIC_LVT_MASKED); - write_register(APIC_REG_LVT_PERFORMANCE_COUNTER, APIC_LVT(0xff, 0) | APIC_LVT_MASKED); - write_register(APIC_REG_LVT_LINT0, APIC_LVT(0x1f, 7) | APIC_LVT_MASKED); - write_register(APIC_REG_LVT_LINT1, APIC_LVT(0xff, 4) | APIC_LVT_TRIGGER_LEVEL); // nmi - write_register(APIC_REG_LVT_ERR, APIC_LVT(0xe3, 0) | APIC_LVT_MASKED); + write_register(APIC_REG_TPR, 0); if (cpu != 0) { static volatile u32 foo = 0; diff --git a/Kernel/Interrupts/SpuriousInterruptHandler.h b/Kernel/Interrupts/SpuriousInterruptHandler.h index 0208b0f4f9..92f36bdce0 100644 --- a/Kernel/Interrupts/SpuriousInterruptHandler.h +++ b/Kernel/Interrupts/SpuriousInterruptHandler.h @@ -30,6 +30,7 @@ #include <AK/OwnPtr.h> #include <AK/Types.h> #include <Kernel/Arch/i386/CPU.h> +#include <Kernel/Interrupts/IRQController.h> #include <Kernel/Interrupts/GenericInterruptHandler.h> namespace Kernel { |