mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 09:22:44 +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:
		
							parent
							
								
									84b7bc5e14
								
							
						
					
					
						commit
						4b847810bf
					
				
					 8 changed files with 47 additions and 101 deletions
				
			
		|  | @ -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); | ||||||
| }; |  | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -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() | ||||||
|  |  | ||||||
|  | @ -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"; | ||||||
|  |  | ||||||
|  | @ -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; | ||||||
|  |  | ||||||
|  | @ -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) | ||||||
|  |  | ||||||
|  | @ -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(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -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; | ||||||
|  |  | ||||||
|  | @ -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()); } | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Andreas Kling
						Andreas Kling