Serenity Operating System
at portability 241 lines 6.4 kB view raw
1/* 2 * Copyright (c) 2020, Liav A. <liavalb@hotmail.co.il> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, this 9 * list of conditions and the following disclaimer. 10 * 11 * 2. Redistributions in binary form must reproduce the above copyright notice, 12 * this list of conditions and the following disclaimer in the documentation 13 * and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 22 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 23 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27#pragma once 28 29#include <AK/Types.h> 30#include <Kernel/VM/Region.h> 31#include <LibBareMetal/Memory/PhysicalAddress.h> 32#include <LibBareMetal/Memory/VirtualAddress.h> 33 34namespace Kernel { 35namespace MultiProcessor { 36 37 struct [[gnu::packed]] FloatingPointer 38 { 39 char sig[4]; 40 u32 physical_address_ptr; 41 u8 length; 42 u8 specification_revision; 43 u8 checksum; 44 u8 feature_info[5]; 45 }; 46 47 struct [[gnu::packed]] EntryHeader 48 { 49 u8 entry_type; 50 }; 51 52 struct [[gnu::packed]] ConfigurationTableHeader 53 { 54 char sig[4]; 55 u16 length; 56 u8 specification_revision; 57 u8 checksum; 58 char oem_id[8]; 59 char product_id[12]; 60 u32 oem_table_ptr; 61 u16 oem_table_size; 62 u16 entry_count; 63 u32 local_apic_address; 64 u16 ext_table_length; 65 u8 ext_table_checksum; 66 u8 reserved; 67 EntryHeader entries[]; 68 }; 69 70 enum class ConfigurationTableEntryType { 71 Processor = 0, 72 Bus = 1, 73 IOAPIC = 2, 74 IO_Interrupt_Assignment = 3, 75 Local_Interrupt_Assignment = 4, 76 SystemAddressSpaceMapping = 128, 77 BusHierarchyDescriptor = 129, 78 CompatibilityBusAddressSpaceModifier = 130 79 }; 80 81 enum class ConfigurationTableEntryLength { 82 Processor = 20, 83 Bus = 8, 84 IOAPIC = 8, 85 IO_Interrupt_Assignment = 8, 86 Local_Interrupt_Assignment = 8, 87 SystemAddressSpaceMapping = 20, 88 BusHierarchyDescriptor = 8, 89 CompatibilityBusAddressSpaceModifier = 8 90 }; 91 92 struct [[gnu::packed]] ExtEntryHeader 93 { 94 u8 entry_type; 95 u8 entry_length; 96 }; 97 98 struct [[gnu::packed]] ProcessorEntry 99 { 100 EntryHeader h; 101 u8 local_apic_id; 102 u8 local_apic_version; 103 u8 cpu_flags; 104 u32 cpu_signature; 105 u32 feature_flags; 106 u8 reserved[8]; 107 }; 108 109 struct [[gnu::packed]] BusEntry 110 { 111 EntryHeader h; 112 u8 bus_id; 113 char bus_type[6]; 114 }; 115 116 struct [[gnu::packed]] IOAPICEntry 117 { 118 EntryHeader h; 119 u8 ioapic_id; 120 u8 ioapic_version; 121 u8 ioapic_flags; 122 u32 ioapic_address; 123 }; 124 125 enum class InterruptType { 126 INT = 0, 127 NMI = 1, 128 SMI = 2, 129 ExtINT = 3, 130 }; 131 132 struct [[gnu::packed]] IOInterruptAssignmentEntry 133 { 134 EntryHeader h; 135 u8 interrupt_type; 136 u8 polarity; 137 u8 trigger_mode; 138 u8 source_bus_id; 139 u8 source_bus_irq; 140 u8 destination_ioapic_id; 141 u8 destination_ioapic_intin_pin; 142 }; 143 144 struct [[gnu::packed]] LocalInterruptAssignmentEntry 145 { 146 EntryHeader h; 147 u8 interrupt_type; 148 u8 polarity; 149 u8 trigger_mode; 150 u8 source_bus_id; 151 u8 source_bus_irq; 152 u8 destination_lapic_id; 153 u8 destination_lapic_lintin_pin; 154 }; 155 156 enum class SystemAddressType { 157 IO = 0, 158 Memory = 1, 159 Prefetch = 2, 160 }; 161 162 struct [[gnu::packed]] SystemAddressSpaceMappingEntry 163 { 164 ExtEntryHeader h; 165 u8 bus_id; 166 u8 address_type; 167 u64 address_base; 168 u64 length; 169 }; 170 171 struct [[gnu::packed]] BusHierarchyDescriptorEntry 172 { 173 ExtEntryHeader h; 174 u8 bus_id; 175 u8 bus_info; 176 u8 parent_bus; 177 u8 reserved[3]; 178 }; 179 180 struct [[gnu::packed]] CompatibilityBusAddressSpaceModifierEntry 181 { 182 ExtEntryHeader h; 183 u8 bus_id; 184 u8 address_modifier; 185 u32 predefined_range_list; 186 }; 187 188} 189 190class PCIInterruptOverrideMetadata : public RefCounted<PCIInterruptOverrideMetadata> { 191public: 192 PCIInterruptOverrideMetadata(u8 bus_id, u8 polarity, u8 trigger_mode, u8 source_irq, u32 ioapic_id, u16 ioapic_int_pin); 193 u8 bus() const; 194 u8 polarity() const; 195 u8 trigger_mode() const; 196 u8 pci_interrupt_pin() const; 197 u8 pci_device_number() const; 198 u32 ioapic_id() const; 199 u16 ioapic_interrupt_pin() const; 200 201private: 202 u8 m_bus_id; 203 u8 m_polarity; 204 u8 m_trigger_mode; 205 u8 m_pci_interrupt_pin; 206 u8 m_pci_device_number; 207 u32 m_ioapic_id; 208 u16 m_ioapic_interrupt_pin; 209}; 210 211class MultiProcessorParser { 212public: 213 static MultiProcessorParser& the(); 214 215 static bool is_initialized(); 216 static void initialize(); 217 Vector<RefPtr<PCIInterruptOverrideMetadata>> get_pci_interrupt_redirections(); 218 219protected: 220 MultiProcessorParser(); 221 222 void parse_configuration_table(); 223 size_t get_configuration_table_length(); 224 void parse_floating_pointer_data(); 225 226 Vector<unsigned> get_pci_bus_ids(); 227 228 uintptr_t search_floating_pointer(); 229 uintptr_t search_floating_pointer_in_ebda(u16 ebda_segment); 230 uintptr_t search_floating_pointer_in_bios_area(); 231 232 uintptr_t m_floating_pointer; 233 uintptr_t m_configuration_table; 234 Vector<uintptr_t> m_io_interrupt_redirection_entries; 235 Vector<uintptr_t> m_bus_entries; 236 bool m_operable; 237 238 size_t m_configuration_table_length; 239 u8 m_specification_revision; 240}; 241}