ReactOS 0.4.17-dev-966-gf06eace
madt.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS Kernel
3 * LICENSE: MIT (https://spdx.org/licenses/MIT)
4 * PURPOSE: Source File for MADT Table parsing
5 * COPYRIGHT: Copyright 2026 Justin Miller <justin.miller@reactos.org>
6 * Copyright 2023 Serge Gautherie <reactos-git_serge_171003@gautherie.fr>
7 */
8
9/* INCLUDES *******************************************************************/
10
11#include <hal.h>
12#include <acpi.h>
13/* ACPI_BIOS_ERROR defined in acoutput.h and bugcodes.h */
14#undef ACPI_BIOS_ERROR
15#include <smp.h>
16
17#define NDEBUG
18#include <debug.h>
19
20/* GLOBALS ********************************************************************/
21
23
25
27
28/* The table is parsed before debug output works, so problems are reported later */
31
32/* FUNCTIONS ******************************************************************/
33
47static
48VOID
51 _In_ ULONG ProcessorId,
53{
55
56 if (!(Flags & ACPI_MADT_ENABLED))
57 return;
58
59 /* TODO: LapicId holds 8 bits, and 0xFF is the broadcast ID, we eventually want to support x2APIC however. */
60 if (ApicId >= 0xFF)
61 {
63 return;
64 }
65
66 /* Firmware can describe a processor with both a local APIC and a local x2APIC entry */
68 {
69 if (HalpProcessorIdentity[Index].LapicId == ApicId)
70 return;
71 }
72
74 {
76 return;
77 }
78
79 /* FIXME: Only extend tracking when we get x2APIC support */
83}
84
92static
93VOID
95 _In_ ACPI_MADT_IO_APIC *IoApic)
96{
99
100 /* Keep the first unit when an ID is duplicated, because apparently this happens on Dell PowerEdge's sometimes. */
101 if ((IoApic->Address == 0) || (HalpApicInfoTable.IoApicPA[IoApic->Id] != 0))
102 {
104 return;
105 }
106
107 HalpApicInfoTable.IoApicPA[IoApic->Id] = IoApic->Address;
108 HalpApicInfoTable.IoApicIrqBase[IoApic->Id] = IoApic->GlobalIrqBase;
110}
111
119static
120VOID
123{
124 /* Overrides only exist for ISA IRQs */
125 if ((Override->Bus != 0) || (Override->SourceIrq >= RTL_NUMBER_OF(HalpPicVectorRedirect)))
126 {
128 return;
129 }
130
131 HalpPicVectorRedirect[Override->SourceIrq] = Override->GlobalIrq;
132}
133
141static
142VOID
144 _In_ ACPI_TABLE_MADT *MadtTable)
145{
147 ULONG_PTR TableEnd;
148
149 TableEnd = (ULONG_PTR)MadtTable + MadtTable->Header.Length;
150 Entry = (ACPI_SUBTABLE_HEADER *)(MadtTable + 1);
151
152 while ((ULONG_PTR)Entry < TableEnd)
153 {
154 if (((ULONG_PTR)(Entry + 1) > TableEnd) ||
155 (Entry->Length < sizeof(*Entry)) ||
156 ((ULONG_PTR)Entry + Entry->Length > TableEnd))
157 {
159 return;
160 }
161
162 switch (Entry->Type)
163 {
165 {
167
168 if (Entry->Length < sizeof(*LocalApic))
169 {
171 break;
172 }
173
174 HalpMadtAddProcessor(LocalApic->Id,
175 LocalApic->ProcessorId,
176 LocalApic->LapicFlags);
177 break;
178 }
179
181 {
183
184 if (Entry->Length < sizeof(*LocalX2Apic))
185 {
187 break;
188 }
189
191 LocalX2Apic->Uid,
192 LocalX2Apic->LapicFlags);
193 break;
194 }
195
197 {
198 if (Entry->Length < sizeof(ACPI_MADT_IO_APIC))
199 {
201 break;
202 }
203
205 break;
206 }
207
209 {
210 if (Entry->Length < sizeof(ACPI_MADT_INTERRUPT_OVERRIDE))
211 {
213 break;
214 }
215
217 break;
218 }
219
220 /* Other types, including reserved and OEM ones, are skipped */
221 default:
222 break;
223 }
224
226 }
227}
228
238static
239VOID
241{
242 PROCESSOR_IDENTITY BootProcessor;
243 ULONG Index;
244 UCHAR BootApicId;
245
246 /* The kernel fills this from CPUID before initializing the processor with the HAL */
247 BootApicId = (UCHAR)KeGetCurrentPrcb()->InitialApicId;
248
250 {
251 if (HalpProcessorIdentity[Index].LapicId == BootApicId)
252 break;
253 }
254
256 {
257 /* The MADT is missing the boot processor, so we can't trust it and only run the boot processor */
258 RtlZeroMemory(&BootProcessor, sizeof(BootProcessor));
259 BootProcessor.LapicId = BootApicId;
261 }
262 else
263 {
264 /* A conforming MADT lists the boot processor first, so this only moves entries on non-conforming ones */
265 BootProcessor = HalpProcessorIdentity[Index];
268 Index * sizeof(BootProcessor));
269 }
270
271 BootProcessor.BSPCheck = TRUE;
272 HalpProcessorIdentity[0] = BootProcessor;
273}
274
275VOID
277 _In_ PLOADER_PARAMETER_BLOCK LoaderBlock)
278{
279 ACPI_TABLE_MADT *MadtTable;
280
281 MadtTable = HalAcpiGetTable(LoaderBlock, APIC_SIGNATURE);
282 if (MadtTable && (MadtTable->Header.Length >= sizeof(*MadtTable)))
283 {
285 HalpMadtParseEntries(MadtTable);
286 }
287 else
288 {
290 }
291
293}
294
295VOID
297{
298#if DBG
299 ULONG i;
300
301 DPRINT1("Physical processor count: %lu\n", HalpApicInfoTable.ProcessorCount);
302 for (i = 0; i < HalpApicInfoTable.ProcessorCount; i++)
303 {
304 DPRINT1(" Processor %lu: ProcessorId %u, LapicId %u, ProcessorStarted %u, BSPCheck %u, ProcessorPrcb %p\n",
305 i,
306 HalpProcessorIdentity[i].ProcessorId,
307 HalpProcessorIdentity[i].LapicId,
308 HalpProcessorIdentity[i].ProcessorStarted,
309 HalpProcessorIdentity[i].BSPCheck,
310 HalpProcessorIdentity[i].ProcessorPrcb);
311 }
312
314 {
315 if (HalpApicInfoTable.IoApicPA[i] != 0)
316 {
317 DPRINT1(" I/O APIC %lu: Address 0x%08lx, GlobalIrqBase %lu\n",
318 i,
321 }
322 }
323
325 {
326 DPRINT1("MADT missing or malformed: %u, entries ignored: %lu\n",
329 }
330#endif
331}
DWORD Id
#define RTL_NUMBER_OF(x)
Definition: RtlRegistry.c:12
@ ACPI_MADT_TYPE_IO_APIC
Definition: actbl2.h:1006
@ ACPI_MADT_TYPE_LOCAL_X2APIC
Definition: actbl2.h:1014
@ ACPI_MADT_TYPE_INTERRUPT_OVERRIDE
Definition: actbl2.h:1007
@ ACPI_MADT_TYPE_LOCAL_APIC
Definition: actbl2.h:1005
#define ACPI_MADT_ENABLED
Definition: actbl2.h:1455
unsigned char BOOLEAN
Definition: actypes.h:127
#define DPRINT1
Definition: precomp.h:8
_In_ D3DDDI_VIDEO_PRESENT_TARGET_ID _In_ ULONG _In_ ULONG Flags
Definition: dispmprt.h:245
#define TRUE
Definition: types.h:120
#define ULONG_PTR
Definition: config.h:101
#define MAXIMUM_PROCESSORS
Definition: rwlock.h:5
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
PVOID NTAPI HalAcpiGetTable(IN PLOADER_PARAMETER_BLOCK LoaderBlock, IN ULONG Signature)
Definition: halacpi.c:446
#define C_ASSERT(e)
Definition: intsafe.h:73
#define RTL_FIELD_SIZE(type, field)
Definition: kdb_expr.c:86
ULONG HalpPicVectorRedirect[16]
Definition: halacpi.c:40
static VOID HalpMadtAddIoApic(_In_ ACPI_MADT_IO_APIC *IoApic)
Records the I/O APIC of an I/O APIC entry.
Definition: madt.c:94
VOID HalpParseApicTables(_In_ PLOADER_PARAMETER_BLOCK LoaderBlock)
Definition: madt.c:276
static VOID HalpMadtParseEntries(_In_ ACPI_TABLE_MADT *MadtTable)
Walks the interrupt controller entries of the MADT.
Definition: madt.c:143
static VOID HalpMadtAddProcessor(_In_ ULONG ApicId, _In_ ULONG ProcessorId, _In_ ULONG Flags)
Adds the processor of a local APIC or local x2APIC entry.
Definition: madt.c:49
VOID HalpPrintApicTables(VOID)
Definition: madt.c:296
static BOOLEAN HalpMadtTruncated
Definition: madt.c:30
static VOID HalpMadtPlaceBootProcessor(VOID)
Moves the boot processor to the first entry, since NT processor numbers follow the entry order.
Definition: madt.c:240
static ULONG HalpMadtIgnoredEntries
Definition: madt.c:29
HALP_APIC_INFO_TABLE HalpApicInfoTable
Definition: madt.c:22
static VOID HalpMadtAddInterruptOverride(_In_ ACPI_MADT_INTERRUPT_OVERRIDE *Override)
Records the routing of an interrupt source override entry.
Definition: madt.c:121
PROCESSOR_IDENTITY HalpProcessorIdentity[MAXIMUM_PROCESSORS]
Definition: madt.c:24
FORCEINLINE struct _KPRCB * KeGetCurrentPrcb(VOID)
Definition: ketypes.h:1197
#define _In_
Definition: no_sal2.h:158
#define RTL_NUMBER_OF_FIELD(type, field)
Definition: ntbasedef.h:715
#define APIC_SIGNATURE
Definition: acpi.h:33
Entry
Definition: section.c:5216
#define HALP_APIC_INFO_TABLE_IOAPIC_NUMBER
Definition: smp.h:23
ULONG ProcessorCount
Definition: smp.h:27
ULONG IoApicPA[HALP_APIC_INFO_TABLE_IOAPIC_NUMBER]
Definition: smp.h:31
ULONG IOAPICCount
Definition: smp.h:28
ULONG IoApicIrqBase[HALP_APIC_INFO_TABLE_IOAPIC_NUMBER]
Definition: smp.h:32
ULONG LocalApicPA
Definition: smp.h:29
ULONG ProcessorId
Definition: smp.h:13
ULONG LapicId
Definition: smp.h:14
BOOLEAN BSPCheck
Definition: smp.h:16
UINT32 Length
Definition: actbl.h:109
ACPI_TABLE_HEADER Header
Definition: actbl2.h:985
UINT32 Address
Definition: actbl2.h:986
unsigned char UCHAR
Definition: typedefs.h:53
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define RtlMoveMemory(Destination, Source, Length)
Definition: typedefs.h:264
uint32_t ULONG
Definition: typedefs.h:59
_In_ WDFCOLLECTION _In_ ULONG Index
_Must_inspect_result_ typedef _In_ ULONG ApicId
Definition: iotypes.h:1105