Browse Source

Kernel: Allow switching to IOAPIC mode even without enabling SMP

This small change allows to use the IOAPIC by default without to enable
SMP mode, which emulates Uni-Processor setup with IOAPIC instead of
using the PIC.

This opens the opportunity to utilize other types of interrupts like MSI
and MSI-X interrupts.
Liav A 3 years ago
parent
commit
ac7953f945

+ 10 - 0
Kernel/CommandLine.cpp

@@ -111,6 +111,16 @@ UNMAP_AFTER_INIT bool CommandLine::is_smp_enabled() const
     return lookup("smp"sv).value_or("off"sv) == "on"sv;
 }
 
+UNMAP_AFTER_INIT bool CommandLine::is_ioapic_enabled() const
+{
+    auto value = lookup("enable_ioapic"sv).value_or("on"sv);
+    if (value == "on"sv)
+        return true;
+    if (value == "off"sv)
+        return false;
+    PANIC("Unknown enable_ioapic setting: {}", value);
+}
+
 UNMAP_AFTER_INIT bool CommandLine::is_vmmouse_enabled() const
 {
     return lookup("vmmouse"sv).value_or("on"sv) == "on"sv;

+ 1 - 0
Kernel/CommandLine.h

@@ -59,6 +59,7 @@ public:
 
     [[nodiscard]] bool is_boot_profiling_enabled() const;
     [[nodiscard]] bool is_ide_enabled() const;
+    [[nodiscard]] bool is_ioapic_enabled() const;
     [[nodiscard]] bool is_smp_enabled() const;
     [[nodiscard]] bool is_physical_networking_disabled() const;
     [[nodiscard]] bool is_vmmouse_enabled() const;

+ 25 - 24
Kernel/Interrupts/APIC.cpp

@@ -270,29 +270,32 @@ UNMAP_AFTER_INIT bool APIC::init_bsp()
         return false;
     }
 
-    auto madt = Memory::map_typed<ACPI::Structures::MADT>(madt_address.value());
-    size_t entry_index = 0;
-    size_t entries_length = madt->h.length - sizeof(ACPI::Structures::MADT);
-    auto* madt_entry = madt->entries;
-    while (entries_length > 0) {
-        size_t entry_length = madt_entry->length;
-        if (madt_entry->type == (u8)ACPI::Structures::MADTEntryType::LocalAPIC) {
-            auto* plapic_entry = (const ACPI::Structures::MADTEntries::ProcessorLocalAPIC*)madt_entry;
-            dbgln_if(APIC_DEBUG, "APIC: AP found @ MADT entry {}, processor ID: {}, xAPIC ID: {}, flags: {:#08x}", entry_index, plapic_entry->acpi_processor_id, plapic_entry->apic_id, plapic_entry->flags);
-            m_processor_cnt++;
-            if ((plapic_entry->flags & 0x1) != 0)
-                m_processor_enabled_cnt++;
-        } else if (madt_entry->type == (u8)ACPI::Structures::MADTEntryType::Local_x2APIC) {
-            // Only used for APID IDs >= 255
-            auto* plx2apic_entry = (const ACPI::Structures::MADTEntries::ProcessorLocalX2APIC*)madt_entry;
-            dbgln_if(APIC_DEBUG, "APIC: AP found @ MADT entry {}, processor ID: {}, x2APIC ID: {}, flags: {:#08x}", entry_index, plx2apic_entry->acpi_processor_id, plx2apic_entry->apic_id, plx2apic_entry->flags);
-            m_processor_cnt++;
-            if ((plx2apic_entry->flags & 0x1) != 0)
-                m_processor_enabled_cnt++;
+    if (kernel_command_line().is_smp_enabled()) {
+        auto madt = Memory::map_typed<ACPI::Structures::MADT>(madt_address.value());
+        size_t entry_index = 0;
+        size_t entries_length = madt->h.length - sizeof(ACPI::Structures::MADT);
+        auto* madt_entry = madt->entries;
+        while (entries_length > 0) {
+            size_t entry_length = madt_entry->length;
+            if (madt_entry->type == (u8)ACPI::Structures::MADTEntryType::LocalAPIC) {
+                auto* plapic_entry = (const ACPI::Structures::MADTEntries::ProcessorLocalAPIC*)madt_entry;
+                dbgln_if(APIC_DEBUG, "APIC: AP found @ MADT entry {}, processor ID: {}, xAPIC ID: {}, flags: {:#08x}", entry_index, plapic_entry->acpi_processor_id, plapic_entry->apic_id, plapic_entry->flags);
+                m_processor_cnt++;
+                if ((plapic_entry->flags & 0x1) != 0)
+                    m_processor_enabled_cnt++;
+            } else if (madt_entry->type == (u8)ACPI::Structures::MADTEntryType::Local_x2APIC) {
+                // Only used for APID IDs >= 255
+                auto* plx2apic_entry = (const ACPI::Structures::MADTEntries::ProcessorLocalX2APIC*)madt_entry;
+                dbgln_if(APIC_DEBUG, "APIC: AP found @ MADT entry {}, processor ID: {}, x2APIC ID: {}, flags: {:#08x}", entry_index, plx2apic_entry->acpi_processor_id, plx2apic_entry->apic_id, plx2apic_entry->flags);
+                m_processor_cnt++;
+                if ((plx2apic_entry->flags & 0x1) != 0)
+                    m_processor_enabled_cnt++;
+            }
+            madt_entry = (ACPI::Structures::MADTEntryHeader*)(VirtualAddress(madt_entry).offset(entry_length).get());
+            entries_length -= entry_length;
+            entry_index++;
         }
-        madt_entry = (ACPI::Structures::MADTEntryHeader*)(VirtualAddress(madt_entry).offset(entry_length).get());
-        entries_length -= entry_length;
-        entry_index++;
+        dbgln("APIC processors found: {}, enabled: {}", m_processor_cnt, m_processor_enabled_cnt);
     }
 
     if (m_processor_enabled_cnt < 1)
@@ -300,8 +303,6 @@ UNMAP_AFTER_INIT bool APIC::init_bsp()
     if (m_processor_cnt < 1)
         m_processor_cnt = 1;
 
-    dbgln("APIC processors found: {}, enabled: {}", m_processor_cnt, m_processor_enabled_cnt);
-
     enable(0);
     return true;
 }

+ 4 - 4
Kernel/Interrupts/InterruptManagement.cpp

@@ -41,10 +41,10 @@ UNMAP_AFTER_INIT void InterruptManagement::initialize()
     VERIFY(!InterruptManagement::initialized());
     s_interrupt_management = new InterruptManagement();
 
-    if (kernel_command_line().is_smp_enabled())
-        InterruptManagement::the().switch_to_ioapic_mode();
-    else
+    if (!kernel_command_line().is_ioapic_enabled() && !kernel_command_line().is_smp_enabled())
         InterruptManagement::the().switch_to_pic_mode();
+    else
+        InterruptManagement::the().switch_to_ioapic_mode();
 }
 
 void InterruptManagement::enumerate_interrupt_handlers(Function<void(GenericInterruptHandler&)> callback)
@@ -220,7 +220,7 @@ UNMAP_AFTER_INIT void InterruptManagement::locate_apic_data()
             dbgln("Interrupts: Overriding INT {:#x} with GSI {}, for bus {:#x}",
                 interrupt_override_entry->source,
                 global_system_interrupt,
-                flags);
+                interrupt_override_entry->bus);
         }
         madt_entry = (ACPI::Structures::MADTEntryHeader*)(VirtualAddress(madt_entry).offset(entry_length).get());
         entries_length -= entry_length;

+ 1 - 1
Kernel/init.cpp

@@ -271,7 +271,7 @@ void init_stage2(void*)
 
     WorkQueue::initialize();
 
-    if (APIC::initialized() && APIC::the().enabled_processor_count() > 1) {
+    if (kernel_command_line().is_smp_enabled() && APIC::initialized() && APIC::the().enabled_processor_count() > 1) {
         // We can't start the APs until we have a scheduler up and running.
         // We need to be able to process ICI messages, otherwise another
         // core may send too many and end up deadlocking once the pool is