HyperDbg Debugger
Loading...
Searching...
No Matches
Apic.c File Reference

Routines for Advanced Programmable Interrupt Controller (APIC). More...

#include "pch.h"

Functions

UINT64 IoApicRead (volatile IO_APIC_ENT *IoApicBaseVa, UINT32 Reg)
 Perform read I/O APIC.
VOID IoApicWrite (volatile IO_APIC_ENT *IoApicBaseVa, UINT32 Reg, UINT64 Data)
 Perform write to I/O APIC.
VOID ApicDumpIoApic (IO_APIC_ENTRY_PACKETS *IoApicPackets)
 Dump I/O APIC.
VOID XApicIcrWrite (UINT32 Low, UINT32 High)
 Trigger NMI on XAPIC.
VOID X2ApicIcrWrite (UINT32 Low, UINT32 High)
 Trigger NMI on X2APIC.
UINT64 X2ApicRead (UINT32 Offset)
 Read x2APIC mode.
BOOLEAN ApicStoretLocalApicInXApicMode (PLAPIC_PAGE LApicBuffer)
 Store the local APIC in XAPIC mode.
BOOLEAN ApicStoreLocalApicInX2ApicMode (PLAPIC_PAGE LApicBuffer)
 Store the local APIC in X2APIC mode.
VOID ApicTriggerGenericNmi ()
 Trigger NMI on X2APIC or APIC based on Current system.
VOID ApicTriggerGenericSmi ()
 Trigger NMI on X2APIC or APIC based on Current system.
BOOLEAN ApicStoreLocalApicFields (PLAPIC_PAGE LApicBuffer, PBOOLEAN IsUsingX2APIC)
 Store the details of APIC in xAPIC and x2APIC mode.
BOOLEAN ApicStoreIoApicFields (IO_APIC_ENTRY_PACKETS *IoApicPackets)
 Store the details of I/O APIC.
BOOLEAN ApicInitialize ()
 Initialize APIC.
VOID ApicUninitialize ()
 Uninitialize APIC.
VOID ApicSelfIpi (UINT32 Vector)
 Self IPI the current core.

Detailed Description

Routines for Advanced Programmable Interrupt Controller (APIC).

Author
Sina Karvandi (sina@.nosp@m.hype.nosp@m.rdbg..nosp@m.org)

The code is derived from (https://www.cpl0.com/blog/?p=46) and the code for showing the APIC details in the XAPIC is derived from bitdefender/napoca project which is enhanced to support X2APIC mode in HyperDbg

Version
0.1
Date
2020-12-31

Function Documentation

◆ ApicDumpIoApic()

VOID ApicDumpIoApic ( IO_APIC_ENTRY_PACKETS * IoApicPackets)

Dump I/O APIC.

Parameters
IoApicPackets
Returns
VOID
79{
80 UINT32 Index = 0;
81 UINT32 Max;
82 UINT64 Ll, Lh;
83
84 UINT64 ApicBasePa = IO_APIC_DEFAULT_BASE_ADDR;
85
87
88 Max = (Ll >> 16) & 0xff;
89
90 // Log("IoApic @ %08x ID:%x (%x) Arb:%x\n",
91 // ApicBasePa,
92 // IoApicRead(g_IoApicBase, IO_ID_REGISTER) >> 24,
93 // Ll & 0xFF,
94 // IoApicRead(g_IoApicBase, IO_ARB_ID_REGISTER));
95
96 //
97 // Fill the I/O APIC
98 //
99 IoApicPackets->ApicBasePa = (UINT32)ApicBasePa;
100 IoApicPackets->ApicBaseVa = (UINT64)g_IoApicBase;
102 IoApicPackets->IoLl = (UINT32)Ll;
104
105 //
106 // Dump inti table
107 //
108 Max *= 2;
109
110 for (Index = 0; Index <= Max; Index += 2)
111 {
113 {
114 //
115 // To prevent overflow of the target buffer
116 //
117 return;
118 }
119
120 Ll = IoApicRead(g_IoApicBase, IO_REDIR_BASE + Index + 0);
121 Lh = IoApicRead(g_IoApicBase, IO_REDIR_BASE + Index + 1);
122
123 IoApicPackets->LlLhData[Index] = Ll;
124 IoApicPackets->LlLhData[Index + 1] = Lh;
125 }
126}
UINT64 IoApicRead(volatile IO_APIC_ENT *IoApicBaseVa, UINT32 Reg)
Perform read I/O APIC.
Definition Apic.c:26
#define IO_REDIR_BASE
Definition Apic.h:203
#define IO_VERS_REGISTER
Definition Apic.h:201
#define IO_APIC_DEFAULT_BASE_ADDR
Definition Apic.h:159
#define IO_ID_REGISTER
Definition Apic.h:200
#define IO_ARB_ID_REGISTER
Definition Apic.h:202
unsigned int UINT32
Definition BasicTypes.h:54
#define MAX_NUMBER_OF_IO_APIC_ENTRIES
Maximum number of I/O APIC entries.
Definition RequestStructures.h:1222
VOID * g_IoApicBase
I/O APIC Base.
Definition GlobalVariables.h:74
UINT32 IoIdReg
Definition RequestStructures.h:1232
UINT64 ApicBaseVa
Definition RequestStructures.h:1231
UINT32 IoArbIdReg
Definition RequestStructures.h:1234
UINT64 LlLhData[MAX_NUMBER_OF_IO_APIC_ENTRIES]
Definition RequestStructures.h:1235
UINT32 IoLl
Definition RequestStructures.h:1233
UINT64 ApicBasePa
Definition RequestStructures.h:1230

◆ ApicInitialize()

BOOLEAN ApicInitialize ( )

Initialize APIC.

Returns
BOOLEAN
367{
368 UINT64 ApicBaseMSR;
369 PHYSICAL_ADDRESS PaApicBase;
370 PHYSICAL_ADDRESS PaIoApicBase;
371
372 ApicBaseMSR = CpuReadMsr(IA32_APIC_BASE);
373
374 if (!(ApicBaseMSR & (1 << 11)))
375 {
376 return FALSE;
377 }
378
379 //
380 // Map I/O APIC default base address
381 //
382 // The exact APIC base address should be read from MADT table (ACPI)
383 // However, we don't have an ACPI parser right now, but the address
384 // is proved to stay at this (default) physical address since Intel
385 // recommends OS/BIOS to not relocate it, but it could be relocated
386 // however, this address is valid for almost all of the systems
387 //
388 PaIoApicBase.QuadPart = IO_APIC_DEFAULT_BASE_ADDR & 0xFFFFFF000;
389 g_IoApicBase = MmMapIoSpace(PaIoApicBase, 0x1000, MmNonCached);
390
391 if (!g_IoApicBase)
392 {
393 //
394 // Not gonna fail the initialization since the IOAPIC might be relocated by
395 // either OS/BIOS
396 //
397
398 // return FALSE;
399 }
400
401 if (ApicBaseMSR & (1 << 10))
402 {
403 g_CompatibilityCheck.IsX2Apic = TRUE;
404
405 return FALSE;
406 }
407 else
408 {
409 PaApicBase.QuadPart = ApicBaseMSR & 0xFFFFFF000;
410 g_ApicBase = MmMapIoSpace(PaApicBase, 0x1000, MmNonCached);
411
412 if (!g_ApicBase)
413 {
414 return FALSE;
415 }
416
417 g_CompatibilityCheck.IsX2Apic = FALSE;
418 }
419
420 return TRUE;
421}
UINT64 CpuReadMsr(ULONG MsrAddress)
Read an MSR.
Definition PlatformIntrinsics.c:213
#define TRUE
Definition BasicTypes.h:114
#define FALSE
Definition BasicTypes.h:113
COMPATIBILITY_CHECKS_STATUS g_CompatibilityCheck
Different attributes and compatibility checks of the current processor.
Definition GlobalVariables.h:26
VOID * g_ApicBase
Local APIC Base.
Definition GlobalVariables.h:68

◆ ApicSelfIpi()

VOID ApicSelfIpi ( UINT32 Vector)

Self IPI the current core.

Parameters
Vector
Returns
VOID
456{
457 //
458 // Check and apply self-IPI to x2APIC and xAPIC
459 //
460 if (g_CompatibilityCheck.IsX2Apic)
461 {
463 }
464 else
465 {
467 }
468}
VOID XApicIcrWrite(UINT32 Low, UINT32 High)
Trigger NMI on XAPIC.
Definition Apic.c:136
VOID X2ApicIcrWrite(UINT32 Low, UINT32 High)
Trigger NMI on X2APIC.
Definition Apic.c:150
#define APIC_DM_FIXED
Definition Apic.h:79
#define APIC_DEST_SELF
Definition Apic.h:67
#define APIC_DEST_PHYSICAL
Definition Apic.h:78

◆ ApicStoreIoApicFields()

BOOLEAN ApicStoreIoApicFields ( IO_APIC_ENTRY_PACKETS * IoApicPackets)

Store the details of I/O APIC.

Parameters
IoApicPackets
Returns
BOOLEAN
346{
347 //
348 // Dump I/O APIC Entries
349 // Note that I/O APIC is not accessed through MSRs (e.g., X2APIC)
350 // So, it's all about the physical memory
351 //
352 ApicDumpIoApic(IoApicPackets);
353
354 //
355 // There is not error defined for it at the moment
356 //
357 return TRUE;
358}
VOID ApicDumpIoApic(IO_APIC_ENTRY_PACKETS *IoApicPackets)
Dump I/O APIC.
Definition Apic.c:78

◆ ApicStoreLocalApicFields()

BOOLEAN ApicStoreLocalApicFields ( PLAPIC_PAGE LApicBuffer,
PBOOLEAN IsUsingX2APIC )

Store the details of APIC in xAPIC and x2APIC mode.

Parameters
LApicBuffer
IsUsingX2APIC
Returns
BOOLEAN
325{
326 if (g_CompatibilityCheck.IsX2Apic)
327 {
328 *IsUsingX2APIC = TRUE;
329 return ApicStoreLocalApicInX2ApicMode(LApicBuffer);
330 }
331 else
332 {
333 *IsUsingX2APIC = FALSE;
334 return ApicStoretLocalApicInXApicMode(LApicBuffer);
335 }
336}
BOOLEAN ApicStoreLocalApicInX2ApicMode(PLAPIC_PAGE LApicBuffer)
Store the local APIC in X2APIC mode.
Definition Apic.c:233
BOOLEAN ApicStoretLocalApicInXApicMode(PLAPIC_PAGE LApicBuffer)
Store the local APIC in XAPIC mode.
Definition Apic.c:173

◆ ApicStoreLocalApicInX2ApicMode()

BOOLEAN ApicStoreLocalApicInX2ApicMode ( PLAPIC_PAGE LApicBuffer)

Store the local APIC in X2APIC mode.

Returns
BOOLEAN
234{
235 //
236 // Store fields
237 //
238 LApicBuffer->Id = (UINT32)X2ApicRead(APIC_ID);
239 LApicBuffer->Version = (UINT32)X2ApicRead(APIC_VERSION);
240 LApicBuffer->SpuriousInterruptVector = (UINT32)X2ApicRead(APIC_SPURIOUS_INTERRUPT_VECTOR);
241 LApicBuffer->TPR = (UINT32)X2ApicRead(APIC_TASK_PRIORITY);
242 LApicBuffer->ProcessorPriority = (UINT32)X2ApicRead(APIC_PROCESSOR_PRIORITY);
243 LApicBuffer->LogicalDestination = (UINT32)X2ApicRead(APIC_LOGICAL_DESTINATION);
244 LApicBuffer->ErrorStatus = (UINT32)X2ApicRead(APIC_ERROR_STATUS);
245 LApicBuffer->LvtLINT0 = (UINT32)X2ApicRead(APIC_LVT_LINT0);
246 LApicBuffer->LvtLINT1 = (UINT32)X2ApicRead(APIC_LVT_LINT1);
247 LApicBuffer->LvtCmci = (UINT32)X2ApicRead(APIC_LVT_CORRECTED_MACHINE_CHECK_INTERRUPT);
248 LApicBuffer->LvtPerfMonCounters = (UINT32)X2ApicRead(APIC_LVT_PERFORMANCE_MONITORING_COUNTERS);
249 LApicBuffer->LvtTimer = (UINT32)X2ApicRead(APIC_LVT_TIMER);
250 LApicBuffer->LvtThermalSensor = (UINT32)X2ApicRead(APIC_LVT_THERMAL_SENSOR);
251 LApicBuffer->LvtError = (UINT32)X2ApicRead(APIC_LVT_ERROR);
252 LApicBuffer->InitialCount = (UINT32)X2ApicRead(APIC_INITIAL_COUNT);
253 LApicBuffer->CurrentCount = (UINT32)X2ApicRead(APIC_CURRENT_COUNT);
254 LApicBuffer->DivideConfiguration = (UINT32)X2ApicRead(APIC_DIVIDE_CONFIGURATION);
255
256 //
257 // Save the ISR, TMR and IRR
258 //
259 for (UINT32 i = 0; i < 8; i++)
260 {
261 LApicBuffer->ISR[i * 4] = (UINT32)X2ApicRead(APIC_IN_SERVICE_BITS_31_0 + (0x10 * i));
262 }
263
264 for (UINT32 i = 0; i < 8; i++)
265 {
266 LApicBuffer->TMR[i * 4] = (UINT32)X2ApicRead(APIC_TRIGGER_MODE_BITS_31_0 + (0x10 * i));
267 }
268
269 for (UINT32 i = 0; i < 8; i++)
270 {
271 LApicBuffer->IRR[i * 4] = (UINT32)X2ApicRead(APIC_INTERRUPT_REQUEST_BITS_31_0 + (0x10 * i));
272 }
273
274 return TRUE;
275}
UINT64 X2ApicRead(UINT32 Offset)
Read x2APIC mode.
Definition Apic.c:162
UINT32 LvtLINT1
Definition RequestStructures.h:1192
UINT32 LvtError
Definition RequestStructures.h:1195
UINT32 TMR[32]
Definition RequestStructures.h:1162
UINT32 Version
Definition RequestStructures.h:1131
UINT32 LvtCmci
Definition RequestStructures.h:1171
UINT32 LvtThermalSensor
Definition RequestStructures.h:1183
UINT32 InitialCount
Definition RequestStructures.h:1198
UINT32 CurrentCount
Definition RequestStructures.h:1201
UINT32 ISR[32]
Definition RequestStructures.h:1160
UINT32 DivideConfiguration
Definition RequestStructures.h:1206
UINT32 TPR
Definition RequestStructures.h:1136
UINT32 ErrorStatus
Definition RequestStructures.h:1166
UINT32 LvtTimer
Definition RequestStructures.h:1180
UINT32 LogicalDestination
Definition RequestStructures.h:1151
UINT32 IRR[32]
Definition RequestStructures.h:1164
UINT32 LvtLINT0
Definition RequestStructures.h:1189
UINT32 Id
Definition RequestStructures.h:1128
UINT32 ProcessorPriority
Definition RequestStructures.h:1142
UINT32 LvtPerfMonCounters
Definition RequestStructures.h:1186
UINT32 SpuriousInterruptVector
Definition RequestStructures.h:1157

◆ ApicStoretLocalApicInXApicMode()

BOOLEAN ApicStoretLocalApicInXApicMode ( PLAPIC_PAGE LApicBuffer)

Store the local APIC in XAPIC mode.

Returns
BOOLEAN
174{
175 volatile LAPIC_PAGE * LocalApicVa = g_ApicBase;
176
177 //
178 // Check if the base virtual address of local APIC is valid or not
179 //
180 if (!g_ApicBase)
181 {
182 return FALSE;
183 }
184
185 //
186 // Store fields
187 //
188 LApicBuffer->Id = LocalApicVa->Id;
189 LApicBuffer->Version = LocalApicVa->Version;
190 LApicBuffer->SpuriousInterruptVector = LocalApicVa->SpuriousInterruptVector;
191 LApicBuffer->TPR = LocalApicVa->TPR;
192 LApicBuffer->ProcessorPriority = LocalApicVa->ProcessorPriority;
193 LApicBuffer->LogicalDestination = LocalApicVa->LogicalDestination;
194 LApicBuffer->ErrorStatus = LocalApicVa->ErrorStatus;
195 LApicBuffer->LvtLINT0 = LocalApicVa->LvtLINT0;
196 LApicBuffer->LvtLINT1 = LocalApicVa->LvtLINT1;
197 LApicBuffer->LvtCmci = LocalApicVa->LvtCmci;
198 LApicBuffer->LvtPerfMonCounters = LocalApicVa->LvtPerfMonCounters;
199 LApicBuffer->LvtTimer = LocalApicVa->LvtTimer;
200 LApicBuffer->LvtThermalSensor = LocalApicVa->LvtThermalSensor;
201 LApicBuffer->LvtError = LocalApicVa->LvtError;
202 LApicBuffer->InitialCount = LocalApicVa->InitialCount;
203 LApicBuffer->CurrentCount = LocalApicVa->CurrentCount;
204 LApicBuffer->DivideConfiguration = LocalApicVa->DivideConfiguration;
205
206 //
207 // Save the ISR, TMR and IRR
208 //
209 for (UINT32 i = 0; i < 8; i++)
210 {
211 LApicBuffer->ISR[i * 4] = LocalApicVa->ISR[i * 4];
212 }
213
214 for (UINT32 i = 0; i < 8; i++)
215 {
216 LApicBuffer->TMR[i * 4] = LocalApicVa->TMR[i * 4];
217 }
218
219 for (UINT32 i = 0; i < 8; i++)
220 {
221 LApicBuffer->IRR[i * 4] = LocalApicVa->IRR[i * 4];
222 }
223
224 return TRUE;
225}
struct _LAPIC_PAGE LAPIC_PAGE
LAPIC structure and offsets.

◆ ApicTriggerGenericNmi()

VOID ApicTriggerGenericNmi ( )

Trigger NMI on X2APIC or APIC based on Current system.

Returns
VOID
284{
285 if (g_CompatibilityCheck.IsX2Apic)
286 {
287 X2ApicIcrWrite((4 << 8) | (1 << 14) | (3 << 18), 0);
288 }
289 else
290 {
291 XApicIcrWrite((4 << 8) | (1 << 14) | (3 << 18), 0);
292 }
293}

◆ ApicTriggerGenericSmi()

VOID ApicTriggerGenericSmi ( )

Trigger NMI on X2APIC or APIC based on Current system.

Returns
VOID
302{
303 LogInfo("Generating SMIs");
304 if (g_CompatibilityCheck.IsX2Apic)
305 {
306 // X2ApicIcrWrite((4 << 8) | (1 << 14) | (3 << 18), 0);
307 X2ApicIcrWrite((2 << 8) | (1 << 14) | (3 << 18), 0);
308 }
309 else
310 {
311 // XApicIcrWrite((4 << 8) | (1 << 14) | (3 << 18), 0);
312 XApicIcrWrite((2 << 8) | (1 << 14) | (3 << 18), 0);
313 }
314}
#define LogInfo(format,...)
Define log variables.
Definition HyperDbgHyperLogIntrinsics.h:71

◆ ApicUninitialize()

VOID ApicUninitialize ( )

Uninitialize APIC.

Returns
VOID
430{
431 //
432 // Unmap Local APIC base
433 //
434 if (g_ApicBase)
435 {
436 MmUnmapIoSpace(g_ApicBase, 0x1000);
437 }
438
439 //
440 // Unmap I/O APIC base
441 //
442 if (g_IoApicBase)
443 {
444 MmUnmapIoSpace(g_IoApicBase, 0x1000);
445 }
446}

◆ IoApicRead()

UINT64 IoApicRead ( volatile IO_APIC_ENT * IoApicBaseVa,
UINT32 Reg )

Perform read I/O APIC.

Parameters
IoApicBaseVa
Reg
Returns
UINT64
27{
28 UINT32 High = 0, Low;
29
30 IoApicBaseVa->Reg = Reg;
31 Low = IoApicBaseVa->Data;
32
33 if (Reg >= IOAPIC_REDTBL(0) && Reg < IOAPIC_REDTBL(IOAPIC_REDTBL_MAX))
34 {
35 // ASSERT(Reg % 2 == 0);
36 Reg++;
37 IoApicBaseVa->Reg = Reg;
38 High = IoApicBaseVa->Data;
39 return IOAPIC_APPEND_QWORD(High, Low);
40 }
41 else
42 {
43 return Low;
44 }
45}
#define IOAPIC_REDTBL_MAX
Definition Apic.h:166
#define IOAPIC_REDTBL(x)
Definition Apic.h:165
#define IOAPIC_APPEND_QWORD(hi, lo)
Definition Apic.h:161

◆ IoApicWrite()

VOID IoApicWrite ( volatile IO_APIC_ENT * IoApicBaseVa,
UINT32 Reg,
UINT64 Data )

Perform write to I/O APIC.

Parameters
IoApicBaseVa
Reg
Data
Returns
VOID
58{
59 IoApicBaseVa->Reg = Reg;
60 IoApicBaseVa->Data = IOAPIC_LOW_DWORD(Data);
61
62 if (Reg >= IOAPIC_REDTBL(0) && Reg < IOAPIC_REDTBL(IOAPIC_REDTBL_MAX))
63 {
64 // ASSERT(Reg % 2 == 0);
65 Reg++;
66 IoApicBaseVa->Reg = Reg;
67 IoApicBaseVa->Data = IOAPIC_HIGH_DWORD(Data);
68 }
69}
#define IOAPIC_HIGH_DWORD(x)
Definition Apic.h:163
#define IOAPIC_LOW_DWORD(x)
Definition Apic.h:162
Start of Optional Data
Definition script_buffer.hex.txt:8

◆ X2ApicIcrWrite()

VOID X2ApicIcrWrite ( UINT32 Low,
UINT32 High )

Trigger NMI on X2APIC.

Parameters
Low
High
Returns
VOID
151{
152 CpuWriteMsr(X2_MSR_BASE + TO_X2(ICROffset), ((UINT64)High << 32) | Low);
153}
#define ICROffset
Definition Apic.h:19
#define TO_X2(x)
Definition Apic.h:20
#define X2_MSR_BASE
Definition Apic.h:18
VOID CpuWriteMsr(ULONG MsrAddress, UINT64 MsrValue)
Write an MSR.
Definition PlatformIntrinsics.c:233

◆ X2ApicRead()

UINT64 X2ApicRead ( UINT32 Offset)

Read x2APIC mode.

Parameters
Offset
Returns
UINT64
163{
164 return CpuReadMsr(X2_MSR_BASE + TO_X2(Offset));
165}

◆ XApicIcrWrite()

VOID XApicIcrWrite ( UINT32 Low,
UINT32 High )

Trigger NMI on XAPIC.

Parameters
Low
High
Returns
VOID
137{
138 *(UINT32 *)((uintptr_t)g_ApicBase + ICROffset + 0x10) = High;
139 *(UINT32 *)((uintptr_t)g_ApicBase + ICROffset) = Low;
140}