summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLiav A <liavalb@gmail.com>2020-03-06 03:27:08 +0200
committerAndreas Kling <kling@serenityos.org>2020-03-06 10:32:32 +0100
commitc335c94242c061ddcebd3dcb72eb26eb89f7a321 (patch)
treeb772de504b044eb8d9277b8801dabb25f4781754
parenta3fa40fc07e4c27e781839adfe55accddf567ee7 (diff)
downloadserenity-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.cpp37
-rw-r--r--Kernel/Interrupts/SpuriousInterruptHandler.h1
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 {