summaryrefslogtreecommitdiff
path: root/Kernel/Interrupts
diff options
context:
space:
mode:
Diffstat (limited to 'Kernel/Interrupts')
-rw-r--r--Kernel/Interrupts/APIC.cpp300
-rw-r--r--Kernel/Interrupts/APIC.h38
-rw-r--r--Kernel/Interrupts/GenericInterruptHandler.cpp16
-rw-r--r--Kernel/Interrupts/GenericInterruptHandler.h3
-rw-r--r--Kernel/Interrupts/InterruptManagement.cpp3
-rw-r--r--Kernel/Interrupts/UnhandledInterruptHandler.cpp4
6 files changed, 295 insertions, 69 deletions
diff --git a/Kernel/Interrupts/APIC.cpp b/Kernel/Interrupts/APIC.cpp
index 71ae5a8bf6..495b903cf6 100644
--- a/Kernel/Interrupts/APIC.cpp
+++ b/Kernel/Interrupts/APIC.cpp
@@ -30,6 +30,7 @@
#include <AK/Types.h>
#include <Kernel/ACPI/Parser.h>
#include <Kernel/Arch/i386/CPU.h>
+#include <Kernel/Arch/i386/ProcessorInfo.h>
#include <Kernel/IO.h>
#include <Kernel/Interrupts/APIC.h>
#include <Kernel/Interrupts/SpuriousInterruptHandler.h>
@@ -39,8 +40,15 @@
#include <Kernel/VM/TypedMapping.h>
//#define APIC_DEBUG
+//#define APIC_SMP_DEBUG
-#define IRQ_APIC_SPURIOUS 0x7f
+#define IRQ_APIC_IPI (0xfd - IRQ_VECTOR_BASE)
+#define IRQ_APIC_ERR (0xfe - IRQ_VECTOR_BASE)
+#define IRQ_APIC_SPURIOUS (0xff - IRQ_VECTOR_BASE)
+
+#define APIC_ICR_DELIVERY_PENDING (1 << 12)
+
+#define APIC_ENABLED (1 << 8)
#define APIC_BASE_MSR 0x1b
@@ -60,7 +68,67 @@
namespace Kernel {
-static APIC *s_apic;
+static APIC* s_apic;
+
+class APICIPIInterruptHandler final : public GenericInterruptHandler {
+public:
+ explicit APICIPIInterruptHandler(u8 interrupt_vector)
+ : GenericInterruptHandler(interrupt_vector, true)
+ {
+ }
+ virtual ~APICIPIInterruptHandler()
+ {
+ }
+
+ static void initialize(u8 interrupt_number)
+ {
+ new APICIPIInterruptHandler(interrupt_number);
+ }
+
+ virtual void handle_interrupt(const RegisterState&) override;
+
+ virtual bool eoi() override;
+
+ virtual HandlerType type() const override { return HandlerType::IRQHandler; }
+ virtual const char* purpose() const override { return "IPI Handler"; }
+ virtual const char* controller() const override { ASSERT_NOT_REACHED(); }
+
+ virtual size_t sharing_devices_count() const override { return 0; }
+ virtual bool is_shared_handler() const override { return false; }
+ virtual bool is_sharing_with_others() const override { return false; }
+
+private:
+};
+
+class APICErrInterruptHandler final : public GenericInterruptHandler {
+public:
+ explicit APICErrInterruptHandler(u8 interrupt_vector)
+ : GenericInterruptHandler(interrupt_vector, true)
+ {
+ }
+ virtual ~APICErrInterruptHandler()
+ {
+ }
+
+ static void initialize(u8 interrupt_number)
+ {
+ new APICErrInterruptHandler(interrupt_number);
+ }
+
+ virtual void handle_interrupt(const RegisterState&) override;
+
+ virtual bool eoi() override;
+
+ virtual HandlerType type() const override { return HandlerType::IRQHandler; }
+ virtual const char* purpose() const override { return "SMP Error Handler"; }
+ virtual const char* controller() const override { ASSERT_NOT_REACHED(); }
+
+ virtual size_t sharing_devices_count() const override { return 0; }
+ virtual bool is_shared_handler() const override { return false; }
+ virtual bool is_sharing_with_others() const override { return false; }
+
+private:
+};
bool APIC::initialized()
{
@@ -79,8 +147,6 @@ void APIC::initialize()
s_apic = new APIC();
}
-
-
PhysicalAddress APIC::get_base()
{
u32 lo, hi;
@@ -107,6 +173,23 @@ u32 APIC::read_register(u32 offset)
return *reinterpret_cast<volatile u32*>(m_apic_base->vaddr().offset(offset).as_ptr());
}
+void APIC::set_lvt(u32 offset, u8 interrupt)
+{
+ write_register(offset, (read_register(offset) & 0xffffffff) | interrupt);
+}
+
+void APIC::set_siv(u32 offset, u8 interrupt)
+{
+ write_register(offset, (read_register(offset) & 0xffffffff) | interrupt | APIC_ENABLED);
+}
+
+void APIC::wait_for_pending_icr()
+{
+ while ((read_register(APIC_REG_ICR_LOW) & APIC_ICR_DELIVERY_PENDING) != 0) {
+ IO::delay(200);
+ }
+}
+
void APIC::write_icr(const ICRReg& icr)
{
write_register(APIC_REG_ICR_HIGH, icr.high());
@@ -137,9 +220,9 @@ u8 APIC::spurious_interrupt_vector()
return IRQ_APIC_SPURIOUS;
}
-#define APIC_INIT_VAR_PTR(tpe,vaddr,varname) \
+#define APIC_INIT_VAR_PTR(tpe, vaddr, varname) \
reinterpret_cast<volatile tpe*>(reinterpret_cast<ptrdiff_t>(vaddr) \
- + reinterpret_cast<ptrdiff_t>(&varname) \
+ + reinterpret_cast<ptrdiff_t>(&varname) \
- reinterpret_cast<ptrdiff_t>(&apic_ap_start))
bool APIC::init_bsp()
@@ -172,8 +255,6 @@ bool APIC::init_bsp()
return false;
}
- u32 processor_cnt = 0;
- u32 processor_enabled_cnt = 0;
auto madt = map_typed<ACPI::Structures::MADT>(madt_address);
size_t entry_index = 0;
size_t entries_length = madt->h.length - sizeof(ACPI::Structures::MADT);
@@ -184,29 +265,33 @@ bool APIC::init_bsp()
auto* plapic_entry = (const ACPI::Structures::MADTEntries::ProcessorLocalAPIC*)madt_entry;
#ifdef APIC_DEBUG
klog() << "APIC: AP found @ MADT entry " << entry_index << ", Processor Id: " << String::format("%02x", plapic_entry->acpi_processor_id)
- << " APIC Id: " << String::format("%02x", plapic_entry->apic_id) << " Flags: " << String::format("%08x", plapic_entry->flags);
+ << " APIC Id: " << String::format("%02x", plapic_entry->apic_id) << " Flags: " << String::format("%08x", plapic_entry->flags);
#endif
- processor_cnt++;
+ m_processor_cnt++;
if ((plapic_entry->flags & 0x1) != 0)
- processor_enabled_cnt++;
+ m_processor_enabled_cnt++;
}
madt_entry = (ACPI::Structures::MADTEntryHeader*)(VirtualAddress(madt_entry).offset(entry_length).get());
entries_length -= entry_length;
entry_index++;
}
-
- if (processor_enabled_cnt < 1)
- processor_enabled_cnt = 1;
- if (processor_cnt < 1)
- processor_cnt = 1;
- klog() << "APIC Processors found: " << processor_cnt << ", enabled: " << processor_enabled_cnt;
+ if (m_processor_enabled_cnt < 1)
+ m_processor_enabled_cnt = 1;
+ if (m_processor_cnt < 1)
+ m_processor_cnt = 1;
- enable_bsp();
+ klog() << "APIC Processors found: " << m_processor_cnt << ", enabled: " << m_processor_enabled_cnt;
+
+ enable(0);
+ return true;
+}
+
+void APIC::do_boot_aps()
+{
+ if (m_processor_enabled_cnt > 1) {
+ u32 aps_to_enable = m_processor_enabled_cnt - 1;
- if (processor_enabled_cnt > 1) {
- u32 aps_to_enable = processor_enabled_cnt - 1;
-
// Copy the APIC startup code and variables to P0x00008000
// Also account for the data appended to:
// * aps_to_enable u32 values for ap_cpu_init_stacks
@@ -219,17 +304,17 @@ bool APIC::init_bsp()
auto stack_region = MM.allocate_kernel_region(Thread::default_kernel_stack_size, {}, Region::Access::Read | Region::Access::Write, false, true, true);
if (!stack_region) {
klog() << "APIC: Failed to allocate stack for AP #" << i;
- return false;
+ return;
}
stack_region->set_stack(true);
- m_apic_ap_stacks.append(stack_region.release_nonnull());
+ m_apic_ap_stacks.append(move(stack_region));
}
// Store pointers to all stacks for the APs to use
auto ap_stack_array = APIC_INIT_VAR_PTR(u32, apic_startup_region->vaddr().as_ptr(), ap_cpu_init_stacks);
ASSERT(aps_to_enable == m_apic_ap_stacks.size());
for (size_t i = 0; i < aps_to_enable; i++) {
- ap_stack_array[i] = m_apic_ap_stacks[i].vaddr().get() + Thread::default_kernel_stack_size;
+ ap_stack_array[i] = m_apic_ap_stacks[i]->vaddr().get() + Thread::default_kernel_stack_size;
#ifdef APIC_DEBUG
klog() << "APIC: CPU[" << (i + 1) << "] stack at " << VirtualAddress(ap_stack_array[i]);
#endif
@@ -237,9 +322,11 @@ bool APIC::init_bsp()
// Allocate Processor structures for all APs and store the pointer to the data
m_ap_processor_info.resize(aps_to_enable);
+ for (size_t i = 0; i < aps_to_enable; i++)
+ m_ap_processor_info[i] = make<Processor>();
auto ap_processor_info_array = &ap_stack_array[aps_to_enable];
for (size_t i = 0; i < aps_to_enable; i++) {
- ap_processor_info_array[i] = FlatPtr(&m_ap_processor_info.at(i));
+ ap_processor_info_array[i] = FlatPtr(m_ap_processor_info[i].ptr());
#ifdef APIC_DEBUG
klog() << "APIC: CPU[" << (i + 1) << "] Processor at " << VirtualAddress(ap_processor_info_array[i]);
#endif
@@ -248,17 +335,25 @@ bool APIC::init_bsp()
// Store the BSP's CR3 value for the APs to use
*APIC_INIT_VAR_PTR(u32, apic_startup_region->vaddr().as_ptr(), ap_cpu_init_cr3) = MM.kernel_page_directory().cr3();
-
+
// Store the BSP's GDT and IDT for the APs to use
const auto& gdtr = Processor::current().get_gdtr();
*APIC_INIT_VAR_PTR(u32, apic_startup_region->vaddr().as_ptr(), ap_cpu_gdtr) = FlatPtr(&gdtr);
const auto& idtr = get_idtr();
*APIC_INIT_VAR_PTR(u32, apic_startup_region->vaddr().as_ptr(), ap_cpu_idtr) = FlatPtr(&idtr);
-
+
// Store the BSP's CR0 and CR4 values for the APs to use
*APIC_INIT_VAR_PTR(u32, apic_startup_region->vaddr().as_ptr(), ap_cpu_init_cr0) = read_cr0();
*APIC_INIT_VAR_PTR(u32, apic_startup_region->vaddr().as_ptr(), ap_cpu_init_cr4) = read_cr4();
+ // Create an idle thread for each processor. We have to do this here
+ // because we won't be able to send FlushTLB messages, so we have to
+ // have all memory set up for the threads so that when the APs are
+ // starting up, they can access all the memory properly
+ m_ap_idle_threads.resize(aps_to_enable);
+ for (u32 i = 0; i < aps_to_enable; i++)
+ m_ap_idle_threads[i] = Scheduler::create_ap_idle_thread(i + 1);
+
#ifdef APIC_DEBUG
klog() << "APIC: Starting " << aps_to_enable << " AP(s)";
#endif
@@ -287,50 +382,153 @@ bool APIC::init_bsp()
}
#ifdef APIC_DEBUG
- klog() << "APIC: " << processor_enabled_cnt << " processors are initialized and running";
+ klog() << "APIC: " << m_processor_enabled_cnt << " processors are initialized and running";
#endif
}
- return true;
}
-void APIC::enable_bsp()
+void APIC::boot_aps()
{
- // FIXME: Ensure this method can only be executed by the BSP.
- enable(0);
+ // We split this into another call because do_boot_aps() will cause
+ // MM calls upon exit, and we don't want to call smp_enable before that
+ do_boot_aps();
+
+ // Enable SMP, which means IPIs may now be sent
+ Processor::smp_enable();
+
+ // Now trigger all APs to continue execution (need to do this after
+ // the regions have been freed so that we don't trigger IPIs
+ if (m_processor_enabled_cnt > 1)
+ m_apic_ap_continue.store(1, AK::MemoryOrder::memory_order_release);
}
void APIC::enable(u32 cpu)
{
+ if (cpu >= 8) {
+ // TODO: x2apic support?
+ klog() << "SMP support is currently limited to 8 CPUs!";
+ Processor::halt();
+ }
+
+ u32 apic_id = (1u << cpu);
+
+ write_register(APIC_REG_LD, (read_register(APIC_REG_LD) & 0x00ffffff) | (apic_id << 24)); // TODO: only if not in x2apic mode
+
+ // read it back to make sure it's actually set
+ apic_id = read_register(APIC_REG_LD) >> 24;
+ Processor::current().info().set_apic_id(apic_id);
+
#ifdef APIC_DEBUG
- klog() << "Enabling local APIC for cpu #" << cpu;
+ klog() << "Enabling local APIC for cpu #" << cpu << " apic id: " << apic_id;
#endif
if (cpu == 0) {
- // dummy read, apparently to avoid a bug in old CPUs.
- read_register(APIC_REG_SIV);
- // set spurious interrupt vector
- write_register(APIC_REG_SIV, (IRQ_APIC_SPURIOUS + IRQ_VECTOR_BASE) | 0x100);
+ SpuriousInterruptHandler::initialize(IRQ_APIC_SPURIOUS);
- // local destination mode (flat mode)
- write_register(APIC_REG_DF, 0xf0000000);
+ // set error interrupt vector
+ set_lvt(APIC_REG_LVT_ERR, IRQ_APIC_ERR);
+ APICErrInterruptHandler::initialize(IRQ_APIC_ERR);
- // set destination id (note that this limits it to 8 cpus)
- write_register(APIC_REG_LD, 0);
+ // register IPI interrupt vector
+ APICIPIInterruptHandler::initialize(IRQ_APIC_IPI);
+ }
- SpuriousInterruptHandler::initialize(IRQ_APIC_SPURIOUS);
+ // set spurious interrupt vector
+ set_siv(APIC_REG_SIV, IRQ_APIC_SPURIOUS);
+
+ // local destination mode (flat mode)
+ write_register(APIC_REG_DF, 0xf0000000);
- 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(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_TPR, 0);
- } else {
+ write_register(APIC_REG_TPR, 0);
+
+ if (cpu > 0) {
// Notify the BSP that we are done initializing. It will unmap the startup data at P8000
- m_apic_ap_count++;
+ m_apic_ap_count.fetch_add(1, AK::MemoryOrder::memory_order_acq_rel);
+#ifdef APIC_DEBUG
+ klog() << "APIC: cpu #" << cpu << " initialized, waiting for all others";
+#endif
+ // The reason we're making all APs wait until the BSP signals them is that
+ // we don't want APs to trigger IPIs (e.g. through MM) while the BSP
+ // is unable to process them
+ while (!m_apic_ap_continue.load(AK::MemoryOrder::memory_order_consume)) {
+ IO::delay(200);
+ }
+
+ // boot_aps() freed memory, so we need to update our tlb
+ Processor::flush_entire_tlb_local();
}
}
+Thread* APIC::get_idle_thread(u32 cpu) const
+{
+ ASSERT(cpu > 0);
+ return m_ap_idle_threads[cpu - 1];
+}
+
+void APIC::init_finished(u32 cpu)
+{
+ // This method is called once the boot stack is no longer needed
+ ASSERT(cpu > 0);
+ ASSERT(cpu <= m_apic_ap_count);
+ ASSERT(m_apic_ap_stacks[cpu - 1]);
+#ifdef APIC_DEBUG
+ klog() << "APIC: boot stack for for cpu #" << cpu << " no longer needed";
+#endif
+ m_apic_ap_stacks[cpu - 1].clear();
+}
+
+void APIC::broadcast_ipi()
+{
+#ifdef APIC_SMP_DEBUG
+ klog() << "SMP: Broadcast IPI from cpu #" << Processor::current().id();
+#endif
+ wait_for_pending_icr();
+ write_icr(ICRReg(IRQ_APIC_IPI + IRQ_VECTOR_BASE, ICRReg::Fixed, ICRReg::Logical, ICRReg::Assert, ICRReg::TriggerMode::Edge, ICRReg::AllExcludingSelf));
+}
+
+void APIC::send_ipi(u32 cpu)
+{
+ auto& proc = Processor::current();
+#ifdef APIC_SMP_DEBUG
+ klog() << "SMP: Send IPI from cpu #" << proc.id() << " to cpu #" << cpu;
+#endif
+ ASSERT(cpu != proc.id());
+ ASSERT(cpu < 8);
+ wait_for_pending_icr();
+ write_icr(ICRReg(IRQ_APIC_IPI + IRQ_VECTOR_BASE, ICRReg::Fixed, ICRReg::Logical, ICRReg::Assert, ICRReg::TriggerMode::Edge, ICRReg::NoShorthand, 1u << cpu));
+}
+
+void APICIPIInterruptHandler::handle_interrupt(const RegisterState&)
+{
+#ifdef APIC_SMP_DEBUG
+ klog() << "APIC IPI on cpu #" << Processor::current().id();
+#endif
+}
+
+bool APICIPIInterruptHandler::eoi()
+{
+#ifdef APIC_SMP_DEBUG
+ klog() << "SMP: IPI eoi";
+#endif
+ APIC::the().eoi();
+ return true;
+}
+
+void APICErrInterruptHandler::handle_interrupt(const RegisterState&)
+{
+ klog() << "APIC: SMP error on cpu #" << Processor::current().id();
+}
+
+bool APICErrInterruptHandler::eoi()
+{
+ APIC::the().eoi();
+ return true;
+}
+
}
diff --git a/Kernel/Interrupts/APIC.h b/Kernel/Interrupts/APIC.h
index 17a2496fe8..f845c321ab 100644
--- a/Kernel/Interrupts/APIC.h
+++ b/Kernel/Interrupts/APIC.h
@@ -27,11 +27,14 @@
#pragma once
#include <AK/Types.h>
-#include <AK/NonnullOwnPtrVector.h>
#include <Kernel/VM/MemoryManager.h>
namespace Kernel {
+struct LocalAPIC {
+ u32 apic_id;
+};
+
class APIC {
public:
static APIC& the();
@@ -39,14 +42,20 @@ public:
static bool initialized();
bool init_bsp();
- void enable_bsp();
void eoi();
+ void boot_aps();
void enable(u32 cpu);
+ void init_finished(u32 cpu);
+ void broadcast_ipi();
+ void send_ipi(u32 cpu);
static u8 spurious_interrupt_vector();
+ Thread* get_idle_thread(u32 cpu) const;
+ u32 enabled_processor_count() const { return m_processor_enabled_cnt; }
private:
class ICRReg {
- u32 m_reg { 0 };
+ u32 m_low { 0 };
+ u32 m_high { 0 };
public:
enum DeliveryMode {
@@ -76,25 +85,34 @@ private:
AllExcludingSelf = 0x3,
};
- ICRReg(u8 vector, DeliveryMode delivery_mode, DestinationMode destination_mode, Level level, TriggerMode trigger_mode, DestinationShorthand destination)
- : m_reg(vector | (delivery_mode << 8) | (destination_mode << 11) | (level << 14) | (static_cast<u32>(trigger_mode) << 15) | (destination << 18))
+ ICRReg(u8 vector, DeliveryMode delivery_mode, DestinationMode destination_mode, Level level, TriggerMode trigger_mode, DestinationShorthand destinationShort, u8 destination = 0)
+ : m_low(vector | (delivery_mode << 8) | (destination_mode << 11) | (level << 14) | (static_cast<u32>(trigger_mode) << 15) | (destinationShort << 18)),
+ m_high((u32)destination << 24)
{
}
- u32 low() const { return m_reg; }
- u32 high() const { return 0; }
+ u32 low() const { return m_low; }
+ u32 high() const { return m_high; }
};
OwnPtr<Region> m_apic_base;
- NonnullOwnPtrVector<Region> m_apic_ap_stacks;
- Vector<Processor> m_ap_processor_info;
- AK::Atomic<u32> m_apic_ap_count{0};
+ Vector<OwnPtr<Region>> m_apic_ap_stacks;
+ Vector<OwnPtr<Processor>> m_ap_processor_info;
+ Vector<Thread*> m_ap_idle_threads;
+ AK::Atomic<u8> m_apic_ap_count{0};
+ AK::Atomic<u8> m_apic_ap_continue{0};
+ u32 m_processor_cnt{0};
+ u32 m_processor_enabled_cnt{0};
static PhysicalAddress get_base();
static void set_base(const PhysicalAddress& base);
void write_register(u32 offset, u32 value);
u32 read_register(u32 offset);
+ void set_lvt(u32 offset, u8 interrupt);
+ void set_siv(u32 offset, u8 interrupt);
+ void wait_for_pending_icr();
void write_icr(const ICRReg& icr);
+ void do_boot_aps();
};
}
diff --git a/Kernel/Interrupts/GenericInterruptHandler.cpp b/Kernel/Interrupts/GenericInterruptHandler.cpp
index 12f078d811..2101c705e8 100644
--- a/Kernel/Interrupts/GenericInterruptHandler.cpp
+++ b/Kernel/Interrupts/GenericInterruptHandler.cpp
@@ -36,20 +36,28 @@ GenericInterruptHandler& GenericInterruptHandler::from(u8 interrupt_number)
return get_interrupt_handler(interrupt_number);
}
-GenericInterruptHandler::GenericInterruptHandler(u8 interrupt_number)
- : m_interrupt_number(interrupt_number)
+GenericInterruptHandler::GenericInterruptHandler(u8 interrupt_number, bool disable_remap)
+ : m_interrupt_number(interrupt_number),
+ m_disable_remap(disable_remap)
{
- register_generic_interrupt_handler(InterruptManagement::acquire_mapped_interrupt_number(m_interrupt_number), *this);
+ if (m_disable_remap)
+ register_generic_interrupt_handler(m_interrupt_number, *this);
+ else
+ register_generic_interrupt_handler(InterruptManagement::acquire_mapped_interrupt_number(m_interrupt_number), *this);
}
GenericInterruptHandler::~GenericInterruptHandler()
{
- unregister_generic_interrupt_handler(InterruptManagement::acquire_mapped_interrupt_number(m_interrupt_number), *this);
+ if (m_disable_remap)
+ unregister_generic_interrupt_handler(m_interrupt_number, *this);
+ else
+ unregister_generic_interrupt_handler(InterruptManagement::acquire_mapped_interrupt_number(m_interrupt_number), *this);
}
void GenericInterruptHandler::change_interrupt_number(u8 number)
{
ASSERT_INTERRUPTS_ENABLED();
+ ASSERT(!m_disable_remap);
unregister_generic_interrupt_handler(InterruptManagement::acquire_mapped_interrupt_number(interrupt_number()), *this);
m_interrupt_number = number;
register_generic_interrupt_handler(InterruptManagement::acquire_mapped_interrupt_number(interrupt_number()), *this);
diff --git a/Kernel/Interrupts/GenericInterruptHandler.h b/Kernel/Interrupts/GenericInterruptHandler.h
index 61cabf10c1..f479ee3065 100644
--- a/Kernel/Interrupts/GenericInterruptHandler.h
+++ b/Kernel/Interrupts/GenericInterruptHandler.h
@@ -65,11 +65,12 @@ public:
protected:
void change_interrupt_number(u8 number);
- explicit GenericInterruptHandler(u8 interrupt_number);
+ explicit GenericInterruptHandler(u8 interrupt_number, bool disable_remap = false);
private:
size_t m_invoking_count { 0 };
bool m_enabled { false };
u8 m_interrupt_number { 0 };
+ bool m_disable_remap { false };
};
}
diff --git a/Kernel/Interrupts/InterruptManagement.cpp b/Kernel/Interrupts/InterruptManagement.cpp
index 058b45dcd3..e368c811d9 100644
--- a/Kernel/Interrupts/InterruptManagement.cpp
+++ b/Kernel/Interrupts/InterruptManagement.cpp
@@ -188,11 +188,12 @@ void InterruptManagement::switch_to_ioapic_mode()
dbg() << "Interrupts: Detected " << irq_controller->model();
}
}
- APIC::the().init_bsp();
if (auto mp_parser = MultiProcessorParser::autodetect()) {
m_pci_interrupt_overrides = mp_parser->get_pci_interrupt_redirections();
}
+
+ APIC::the().init_bsp();
}
void InterruptManagement::locate_apic_data()
diff --git a/Kernel/Interrupts/UnhandledInterruptHandler.cpp b/Kernel/Interrupts/UnhandledInterruptHandler.cpp
index 077e4db0ba..a9a6b63cb0 100644
--- a/Kernel/Interrupts/UnhandledInterruptHandler.cpp
+++ b/Kernel/Interrupts/UnhandledInterruptHandler.cpp
@@ -35,13 +35,13 @@ UnhandledInterruptHandler::UnhandledInterruptHandler(u8 interrupt_vector)
void UnhandledInterruptHandler::handle_interrupt(const RegisterState&)
{
dbg() << "Interrupt: Unhandled vector " << interrupt_number() << " was invoked for handle_interrupt(RegisterState&).";
- hang();
+ Processor::halt();
}
[[noreturn]] bool UnhandledInterruptHandler::eoi()
{
dbg() << "Interrupt: Unhandled vector " << interrupt_number() << " was invoked for eoi().";
- hang();
+ Processor::halt();
}
UnhandledInterruptHandler::~UnhandledInterruptHandler()