1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 01:48:11 +00:00

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.
This commit is contained in:
Andreas Kling 2020-05-22 13:34:53 +02:00
parent 84b7bc5e14
commit 4b847810bf
8 changed files with 47 additions and 101 deletions

View file

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

View file

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

View file

@ -37,29 +37,20 @@
namespace Kernel { namespace Kernel {
static MultiProcessorParser* s_parser; OwnPtr<MultiProcessorParser> MultiProcessorParser::autodetect()
bool MultiProcessorParser::is_initialized()
{ {
return s_parser != nullptr; auto floating_pointer = find_floating_pointer();
if (!floating_pointer.has_value())
return nullptr;
return adopt_own(*new MultiProcessorParser(floating_pointer.value()));
} }
void MultiProcessorParser::initialize() MultiProcessorParser::MultiProcessorParser(PhysicalAddress floating_pointer)
: m_floating_pointer(floating_pointer)
{ {
ASSERT(!is_initialized()); klog() << "MultiProcessor: Floating Pointer Structure @ " << m_floating_pointer;
s_parser = new MultiProcessorParser; parse_floating_pointer_data();
} parse_configuration_table();
MultiProcessorParser::MultiProcessorParser()
: m_floating_pointer(search_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.";
}
} }
void MultiProcessorParser::parse_floating_pointer_data() 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(); StringView signature("_MP_");
if (!mp_floating_pointer.is_null()) auto mp_floating_pointer = map_ebda().find_chunk_starting_with(signature, 16);
if (mp_floating_pointer.has_value())
return mp_floating_pointer; return mp_floating_pointer;
return search_floating_pointer_in_bios_area(); return map_bios().find_chunk_starting_with(signature, 16);
}
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 {};
} }
Vector<u8> MultiProcessorParser::get_pci_bus_ids() const Vector<u8> MultiProcessorParser::get_pci_bus_ids() const
@ -152,12 +124,6 @@ Vector<u8> MultiProcessorParser::get_pci_bus_ids() const
return pci_bus_ids; return pci_bus_ids;
} }
MultiProcessorParser& MultiProcessorParser::the()
{
ASSERT(is_initialized());
return *s_parser;
}
Vector<PCIInterruptOverrideMetadata> MultiProcessorParser::get_pci_interrupt_redirections() Vector<PCIInterruptOverrideMetadata> MultiProcessorParser::get_pci_interrupt_redirections()
{ {
dbg() << "MultiProcessor: Get PCI IOAPIC redirections"; dbg() << "MultiProcessor: Get PCI IOAPIC redirections";

View file

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

View file

@ -322,29 +322,6 @@ Parser::Parser(PhysicalAddress rsdp)
locate_static_data(); 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) static bool validate_table(const Structures::SDTHeader& v_header, size_t length)
{ {
u8 checksum = 0; u8 checksum = 0;
@ -356,13 +333,13 @@ static bool validate_table(const Structures::SDTHeader& v_header, size_t length)
return false; return false;
} }
PhysicalAddress StaticParsing::find_rsdp() Optional<PhysicalAddress> StaticParsing::find_rsdp()
{ {
klog() << "ACPI: Probing EBDA"; StringView signature("RSD PTR ");
auto rsdp = find_rsdp_in_ebda(); auto rsdp = map_ebda().find_chunk_starting_with(signature, 16);
if (!rsdp.is_null()) if (rsdp.has_value())
return rsdp; 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) PhysicalAddress StaticParsing::find_table(PhysicalAddress rsdp_address, const StringView& signature)

View file

@ -129,9 +129,9 @@ PhysicalAddress InterruptManagement::search_for_madt()
{ {
dbg() << "Early access to ACPI tables for interrupt setup"; dbg() << "Early access to ACPI tables for interrupt setup";
auto rsdp = ACPI::StaticParsing::find_rsdp(); auto rsdp = ACPI::StaticParsing::find_rsdp();
if (rsdp.is_null()) if (!rsdp.has_value())
return {}; return {};
return ACPI::StaticParsing::find_table(rsdp, "APIC"); return ACPI::StaticParsing::find_table(rsdp.value(), "APIC");
} }
InterruptManagement::InterruptManagement() InterruptManagement::InterruptManagement()
@ -189,8 +189,10 @@ void InterruptManagement::switch_to_ioapic_mode()
} }
APIC::init(); APIC::init();
APIC::enable_bsp(); 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() 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();
}
} }

View file

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

View file

@ -39,6 +39,15 @@ struct MappedROM {
size_t offset { 0 }; size_t offset { 0 };
PhysicalAddress paddr; 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()); } PhysicalAddress paddr_of(const u8* ptr) const { return paddr.offset(ptr - this->base()); }
}; };