Serenity Operating System
1/*
2 * Copyright (c) 2020, Liav A. <liavalb@hotmail.co.il>
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 */
6
7#pragma once
8
9#include <AK/Types.h>
10#include <AK/Vector.h>
11#include <Kernel/Memory/Region.h>
12#include <Kernel/PhysicalAddress.h>
13#include <Kernel/VirtualAddress.h>
14
15namespace Kernel {
16namespace MultiProcessor {
17
18struct [[gnu::packed]] FloatingPointer {
19 char sig[4];
20 u32 physical_address_ptr;
21 u8 length;
22 u8 specification_revision;
23 u8 checksum;
24 u8 feature_info[5];
25};
26
27struct [[gnu::packed]] EntryHeader {
28 u8 entry_type;
29};
30
31struct [[gnu::packed]] ConfigurationTableHeader {
32 char sig[4];
33 u16 length;
34 u8 specification_revision;
35 u8 checksum;
36 char oem_id[8];
37 char product_id[12];
38 u32 oem_table_ptr;
39 u16 oem_table_size;
40 u16 entry_count;
41 u32 local_apic_address;
42 u16 ext_table_length;
43 u8 ext_table_checksum;
44 u8 reserved;
45 EntryHeader entries[];
46};
47
48enum class ConfigurationTableEntryType {
49 Processor = 0,
50 Bus = 1,
51 IOAPIC = 2,
52 IO_Interrupt_Assignment = 3,
53 Local_Interrupt_Assignment = 4,
54 SystemAddressSpaceMapping = 128,
55 BusHierarchyDescriptor = 129,
56 CompatibilityBusAddressSpaceModifier = 130
57};
58
59struct [[gnu::packed]] ExtEntryHeader {
60 u8 entry_type;
61 u8 entry_length;
62};
63
64struct [[gnu::packed]] ProcessorEntry {
65 EntryHeader h;
66 u8 local_apic_id;
67 u8 local_apic_version;
68 u8 cpu_flags;
69 u32 cpu_signature;
70 u32 feature_flags;
71 u8 reserved[8];
72};
73
74struct [[gnu::packed]] BusEntry {
75 EntryHeader h;
76 u8 bus_id;
77 char bus_type[6];
78};
79
80struct [[gnu::packed]] IOAPICEntry {
81 EntryHeader h;
82 u8 ioapic_id;
83 u8 ioapic_version;
84 u8 ioapic_flags;
85 u32 ioapic_address;
86};
87
88enum class InterruptType {
89 INT = 0,
90 NMI = 1,
91 SMI = 2,
92 ExtINT = 3,
93};
94
95struct [[gnu::packed]] IOInterruptAssignmentEntry {
96 EntryHeader h;
97 u8 interrupt_type;
98 u8 polarity;
99 u8 trigger_mode;
100 u8 source_bus_id;
101 u8 source_bus_irq;
102 u8 destination_ioapic_id;
103 u8 destination_ioapic_intin_pin;
104};
105
106struct [[gnu::packed]] LocalInterruptAssignmentEntry {
107 EntryHeader h;
108 u8 interrupt_type;
109 u8 polarity;
110 u8 trigger_mode;
111 u8 source_bus_id;
112 u8 source_bus_irq;
113 u8 destination_lapic_id;
114 u8 destination_lapic_lintin_pin;
115};
116
117enum class SystemAddressType {
118 IO = 0,
119 Memory = 1,
120 Prefetch = 2,
121};
122
123struct [[gnu::packed]] SystemAddressSpaceMappingEntry {
124 ExtEntryHeader h;
125 u8 bus_id;
126 u8 address_type;
127 u64 address_base;
128 u64 length;
129};
130
131struct [[gnu::packed]] BusHierarchyDescriptorEntry {
132 ExtEntryHeader h;
133 u8 bus_id;
134 u8 bus_info;
135 u8 parent_bus;
136 u8 reserved[3];
137};
138
139struct [[gnu::packed]] CompatibilityBusAddressSpaceModifierEntry {
140 ExtEntryHeader h;
141 u8 bus_id;
142 u8 address_modifier;
143 u32 predefined_range_list;
144};
145
146}
147
148class PCIInterruptOverrideMetadata;
149
150class MultiProcessorParser final {
151public:
152 static OwnPtr<MultiProcessorParser> autodetect();
153
154 Vector<PCIInterruptOverrideMetadata> get_pci_interrupt_redirections();
155
156private:
157 explicit MultiProcessorParser(PhysicalAddress floating_pointer);
158
159 void parse_configuration_table();
160 void parse_floating_pointer_data();
161
162 Vector<u8> get_pci_bus_ids() const;
163
164 static Optional<PhysicalAddress> find_floating_pointer();
165
166 PhysicalAddress m_floating_pointer;
167 PhysicalAddress m_configuration_table;
168 Vector<MultiProcessor::IOInterruptAssignmentEntry> m_io_interrupt_assignment_entries;
169 Vector<MultiProcessor::BusEntry> m_bus_entries;
170};
171}