Selaa lähdekoodia

Kernel: Simplify scanning BIOS/EBDA and MP parser initialization

Add a MappedROM::find_chunk_starting_with() helper since that's a very
common usage pattern in clients of this code.

Also convert MultiProcessorParser from a persistent singleton object
to a temporary object constructed via a failable factory function.
Andreas Kling 5 vuotta sitten
vanhempi
commit
4b847810bf

+ 4 - 2
Kernel/ACPI/Definitions.h

@@ -336,8 +336,10 @@ class DynamicParser;
 class Parser;
 
 namespace StaticParsing {
-PhysicalAddress find_rsdp();
+Optional<PhysicalAddress> find_rsdp();
 PhysicalAddress find_table(PhysicalAddress rsdp, const StringView& signature);
-};
 }
+
+}
+
 }

+ 3 - 3
Kernel/ACPI/Initialize.cpp

@@ -54,13 +54,13 @@ void initialize()
         return;
 
     auto rsdp = StaticParsing::find_rsdp();
-    if (rsdp.is_null())
+    if (!rsdp.has_value())
         return;
 
     if (feature_level == FeatureLevel::Enabled)
-        Parser::initialize<DynamicParser>(rsdp);
+        Parser::initialize<DynamicParser>(rsdp.value());
     else
-        Parser::initialize<Parser>(rsdp);
+        Parser::initialize<Parser>(rsdp.value());
 }
 
 bool is_enabled()

+ 15 - 49
Kernel/ACPI/MultiProcessorParser.cpp

@@ -37,29 +37,20 @@
 
 namespace Kernel {
 
-static MultiProcessorParser* s_parser;
-
-bool MultiProcessorParser::is_initialized()
-{
-    return s_parser != nullptr;
-}
-
-void MultiProcessorParser::initialize()
+OwnPtr<MultiProcessorParser> MultiProcessorParser::autodetect()
 {
-    ASSERT(!is_initialized());
-    s_parser = new MultiProcessorParser;
+    auto floating_pointer = find_floating_pointer();
+    if (!floating_pointer.has_value())
+        return nullptr;
+    return adopt_own(*new MultiProcessorParser(floating_pointer.value()));
 }
 
-MultiProcessorParser::MultiProcessorParser()
-    : m_floating_pointer(search_floating_pointer())
+MultiProcessorParser::MultiProcessorParser(PhysicalAddress floating_pointer)
+    : m_floating_pointer(floating_pointer)
 {
-    if (!m_floating_pointer.is_null()) {
-        klog() << "MultiProcessor: Floating Pointer Structure @ " << PhysicalAddress(m_floating_pointer);
-        parse_floating_pointer_data();
-        parse_configuration_table();
-    } else {
-        klog() << "MultiProcessor: Can't Locate Floating Pointer Structure, disabled.";
-    }
+    klog() << "MultiProcessor: Floating Pointer Structure @ " << m_floating_pointer;
+    parse_floating_pointer_data();
+    parse_configuration_table();
 }
 
 void MultiProcessorParser::parse_floating_pointer_data()
@@ -114,32 +105,13 @@ void MultiProcessorParser::parse_configuration_table()
     }
 }
 
-PhysicalAddress MultiProcessorParser::search_floating_pointer()
+Optional<PhysicalAddress> MultiProcessorParser::find_floating_pointer()
 {
-    auto mp_floating_pointer = search_floating_pointer_in_ebda();
-    if (!mp_floating_pointer.is_null())
+    StringView signature("_MP_");
+    auto mp_floating_pointer = map_ebda().find_chunk_starting_with(signature, 16);
+    if (mp_floating_pointer.has_value())
         return mp_floating_pointer;
-    return search_floating_pointer_in_bios_area();
-}
-
-PhysicalAddress MultiProcessorParser::search_floating_pointer_in_ebda()
-{
-    klog() << "MultiProcessor: Probing EBDA";
-    auto ebda = map_ebda();
-    for (auto* floating_pointer_str = ebda.base(); floating_pointer_str < ebda.end(); floating_pointer_str += 16) {
-        if (!strncmp("_MP_", (const char*)floating_pointer_str, strlen("_MP_")))
-            return ebda.paddr_of(floating_pointer_str);
-    }
-    return {};
-}
-PhysicalAddress MultiProcessorParser::search_floating_pointer_in_bios_area()
-{
-    auto bios = map_bios();
-    for (auto* floating_pointer_str = bios.base(); floating_pointer_str < bios.end(); floating_pointer_str += 16) {
-        if (!strncmp("_MP_", (const char*)floating_pointer_str, strlen("_MP_")))
-            return bios.paddr_of(floating_pointer_str);
-    }
-    return {};
+    return map_bios().find_chunk_starting_with(signature, 16);
 }
 
 Vector<u8> MultiProcessorParser::get_pci_bus_ids() const
@@ -152,12 +124,6 @@ Vector<u8> MultiProcessorParser::get_pci_bus_ids() const
     return pci_bus_ids;
 }
 
-MultiProcessorParser& MultiProcessorParser::the()
-{
-    ASSERT(is_initialized());
-    return *s_parser;
-}
-
 Vector<PCIInterruptOverrideMetadata> MultiProcessorParser::get_pci_interrupt_redirections()
 {
     dbg() << "MultiProcessor: Get PCI IOAPIC redirections";

+ 5 - 9
Kernel/ACPI/MultiProcessorParser.h

@@ -189,25 +189,21 @@ struct [[gnu::packed]] CompatibilityBusAddressSpaceModifierEntry
 
 class PCIInterruptOverrideMetadata;
 
-class MultiProcessorParser {
+class MultiProcessorParser final {
 public:
-    static MultiProcessorParser& the();
+    static OwnPtr<MultiProcessorParser> autodetect();
 
-    static bool is_initialized();
-    static void initialize();
     Vector<PCIInterruptOverrideMetadata> get_pci_interrupt_redirections();
 
-protected:
-    MultiProcessorParser();
+private:
+    explicit MultiProcessorParser(PhysicalAddress floating_pointer);
 
     void parse_configuration_table();
     void parse_floating_pointer_data();
 
     Vector<u8> get_pci_bus_ids() const;
 
-    PhysicalAddress search_floating_pointer();
-    PhysicalAddress search_floating_pointer_in_ebda();
-    PhysicalAddress search_floating_pointer_in_bios_area();
+    static Optional<PhysicalAddress> find_floating_pointer();
 
     PhysicalAddress m_floating_pointer;
     PhysicalAddress m_configuration_table;

+ 5 - 28
Kernel/ACPI/Parser.cpp

@@ -322,29 +322,6 @@ Parser::Parser(PhysicalAddress rsdp)
     locate_static_data();
 }
 
-static PhysicalAddress find_rsdp_in_ebda()
-{
-    auto ebda = map_ebda();
-    for (auto* rsdp_str = ebda.base(); rsdp_str < ebda.end(); rsdp_str += 16) {
-#ifdef ACPI_DEBUG
-        dbg() << "ACPI: Looking for RSDP in EBDA @ V " << (void*)rsdp_str << ", P " << (void*)p_rsdp_str;
-#endif
-        if (!strncmp("RSD PTR ", (const char*)rsdp_str, strlen("RSD PTR ")))
-            return ebda.paddr_of(rsdp_str);
-    }
-    return {};
-}
-
-static PhysicalAddress find_rsdp_in_bios_area()
-{
-    auto bios = map_bios();
-    for (auto* rsdp_str = bios.base(); rsdp_str < bios.end(); rsdp_str += 16) {
-        if (!strncmp("RSD PTR ", (const char*)rsdp_str, strlen("RSD PTR ")))
-            return bios.paddr_of(rsdp_str);
-    }
-    return {};
-}
-
 static bool validate_table(const Structures::SDTHeader& v_header, size_t length)
 {
     u8 checksum = 0;
@@ -356,13 +333,13 @@ static bool validate_table(const Structures::SDTHeader& v_header, size_t length)
     return false;
 }
 
-PhysicalAddress StaticParsing::find_rsdp()
+Optional<PhysicalAddress> StaticParsing::find_rsdp()
 {
-    klog() << "ACPI: Probing EBDA";
-    auto rsdp = find_rsdp_in_ebda();
-    if (!rsdp.is_null())
+    StringView signature("RSD PTR ");
+    auto rsdp = map_ebda().find_chunk_starting_with(signature, 16);
+    if (rsdp.has_value())
         return rsdp;
-    return find_rsdp_in_bios_area();
+    return map_bios().find_chunk_starting_with(signature, 16);
 }
 
 PhysicalAddress StaticParsing::find_table(PhysicalAddress rsdp_address, const StringView& signature)

+ 6 - 9
Kernel/Interrupts/InterruptManagement.cpp

@@ -129,9 +129,9 @@ PhysicalAddress InterruptManagement::search_for_madt()
 {
     dbg() << "Early access to ACPI tables for interrupt setup";
     auto rsdp = ACPI::StaticParsing::find_rsdp();
-    if (rsdp.is_null())
+    if (!rsdp.has_value())
         return {};
-    return ACPI::StaticParsing::find_table(rsdp, "APIC");
+    return ACPI::StaticParsing::find_table(rsdp.value(), "APIC");
 }
 
 InterruptManagement::InterruptManagement()
@@ -189,8 +189,10 @@ void InterruptManagement::switch_to_ioapic_mode()
     }
     APIC::init();
     APIC::enable_bsp();
-    MultiProcessorParser::initialize();
-    locate_pci_interrupt_overrides();
+
+    if (auto mp_parser = MultiProcessorParser::autodetect()) {
+        m_pci_interrupt_overrides = mp_parser->get_pci_interrupt_redirections();
+    }
 }
 
 void InterruptManagement::locate_apic_data()
@@ -231,9 +233,4 @@ void InterruptManagement::locate_apic_data()
     }
 }
 
-void InterruptManagement::locate_pci_interrupt_overrides()
-{
-    m_pci_interrupt_overrides = MultiProcessorParser::the().get_pci_interrupt_redirections();
-}
-
 }

+ 0 - 1
Kernel/Interrupts/InterruptManagement.h

@@ -88,7 +88,6 @@ private:
     InterruptManagement();
     PhysicalAddress search_for_madt();
     void locate_apic_data();
-    void locate_pci_interrupt_overrides();
     bool m_smp_enabled { false };
     FixedArray<RefPtr<IRQController>> m_interrupt_controllers { 1 };
     Vector<ISAInterruptOverrideMetadata> m_isa_interrupt_overrides;

+ 9 - 0
Kernel/VM/MappedROM.h

@@ -39,6 +39,15 @@ struct MappedROM {
     size_t offset { 0 };
     PhysicalAddress paddr;
 
+    Optional<PhysicalAddress> find_chunk_starting_with(StringView prefix, size_t chunk_size) const
+    {
+        for (auto* candidate = base(); candidate < end(); candidate += chunk_size) {
+            if (!__builtin_memcmp(prefix.characters_without_null_termination(), candidate, prefix.length()))
+                return paddr_of(candidate);
+        }
+        return {};
+    }
+
     PhysicalAddress paddr_of(const u8* ptr) const { return paddr.offset(ptr - this->base()); }
 };