Fix APIC initialization code

This commit is contained in:
Rafal Kupiec 2024-06-06 16:49:08 +02:00
parent ef65bceccd
commit 4212453cf5
Signed by: belliash
GPG Key ID: 4E829243E0CFE6B4
3 changed files with 52 additions and 42 deletions

View File

@ -83,14 +83,14 @@ typedef enum _APIC_DSH
/* APIC message type enumeration list */ /* APIC message type enumeration list */
typedef enum _APIC_MT typedef enum _APIC_MT
{ {
APIC_MT_Fixed = 0, APIC_MT_Fixed,
APIC_MT_LowestPriority = 1, APIC_MT_LowestPriority,
APIC_MT_SMI = 2, APIC_MT_SMI,
APIC_MT_RemoteRead = 3, APIC_MT_RemoteRead,
APIC_MT_NMI = 4, APIC_MT_NMI,
APIC_MT_INIT = 5, APIC_MT_INIT,
APIC_MT_Startup = 6, APIC_MT_Startup,
APIC_MT_ExtInt = 7, APIC_MT_ExtInt,
} APIC_MT, *PAPIC_MT; } APIC_MT, *PAPIC_MT;
/* I8259 PIC interrupt mode enumeration list */ /* I8259 PIC interrupt mode enumeration list */

View File

@ -90,14 +90,14 @@ typedef enum _APIC_DSH
/* APIC message type enumeration list */ /* APIC message type enumeration list */
typedef enum _APIC_MT typedef enum _APIC_MT
{ {
APIC_MT_Fixed = 0, APIC_MT_Fixed,
APIC_MT_LowestPriority = 1, APIC_MT_LowestPriority,
APIC_MT_SMI = 2, APIC_MT_SMI,
APIC_MT_RemoteRead = 3, APIC_MT_RemoteRead,
APIC_MT_NMI = 4, APIC_MT_NMI,
APIC_MT_INIT = 5, APIC_MT_INIT,
APIC_MT_Startup = 6, APIC_MT_Startup,
APIC_MT_ExtInt = 7, APIC_MT_ExtInt,
} APIC_MT, *PAPIC_MT; } APIC_MT, *PAPIC_MT;
/* I8259 PIC interrupt mode enumeration list */ /* I8259 PIC interrupt mode enumeration list */

View File

@ -204,10 +204,10 @@ HlpInitializeApic(VOID)
/* xAPIC compatibility mode specific initialization */ /* xAPIC compatibility mode specific initialization */
if(HlpApicMode == APIC_MODE_COMPAT) if(HlpApicMode == APIC_MODE_COMPAT)
{ {
/* Initialize Destination Format Register with flat model */ /* Initialize Destination Format Register with flat model (not supported in x2APIC mode) */
HlWriteApicRegister(APIC_DFR, APIC_DF_FLAT); HlWriteApicRegister(APIC_DFR, APIC_DF_FLAT);
/* Set the logical APIC ID */ /* Set the logical APIC ID (read-only in x2APIC mode) */
HlWriteApicRegister(APIC_LDR, (1UL << CpuNumber) << 24); HlWriteApicRegister(APIC_LDR, (1UL << CpuNumber) << 24);
} }
@ -218,51 +218,61 @@ HlpInitializeApic(VOID)
SpuriousRegister.CoreChecking = 0; SpuriousRegister.CoreChecking = 0;
HlWriteApicRegister(APIC_SIVR, SpuriousRegister.Long); HlWriteApicRegister(APIC_SIVR, SpuriousRegister.Long);
/* Initialize Logical Vector Table */
LvtRegister.Long = 0;
LvtRegister.MessageType = APIC_DM_FIXED;
LvtRegister.DeliveryStatus = 0;
LvtRegister.RemoteIRR = 0;
LvtRegister.TriggerMode = APIC_TGM_EDGE;
LvtRegister.Mask = 0;
LvtRegister.TimerMode = 0;
/* Mask LVTR_ERROR first, to prevent local APIC error */ /* Mask LVTR_ERROR first, to prevent local APIC error */
LvtRegister.Vector = APIC_VECTOR_ERROR; HlWriteApicRegister(APIC_ERRLVTR, APIC_VECTOR_ERROR);
HlWriteApicRegister(APIC_ERRLVTR, LvtRegister.Long);
/* Mask LVT tables */ /* Mask TMRLVTR */
LvtRegister.Vector = APIC_VECTOR_NMI; LvtRegister.Long = 0;
LvtRegister.Mask = 1;
LvtRegister.MessageType = APIC_DM_FIXED;
LvtRegister.TimerMode = 1;
LvtRegister.TriggerMode = APIC_TGM_EDGE;
LvtRegister.Vector = APIC_VECTOR_PROFILE;
HlWriteApicRegister(APIC_TMRLVTR, LvtRegister.Long); HlWriteApicRegister(APIC_TMRLVTR, LvtRegister.Long);
HlWriteApicRegister(APIC_THRMLVTR, LvtRegister.Long);
/* Mask PCLVTR */
LvtRegister.Long = 0;
LvtRegister.Mask = 0;
LvtRegister.MessageType = APIC_DM_FIXED;
LvtRegister.TimerMode = 0;
LvtRegister.TriggerMode = APIC_TGM_EDGE;
LvtRegister.Vector = APIC_VECTOR_PERF;
HlWriteApicRegister(APIC_PCLVTR, LvtRegister.Long); HlWriteApicRegister(APIC_PCLVTR, LvtRegister.Long);
/* Mask LINT0 */ /* Mask LINT0 */
LvtRegister.Long = 0;
LvtRegister.Mask = 1;
LvtRegister.MessageType = APIC_DM_FIXED;
LvtRegister.TimerMode = 0;
LvtRegister.TriggerMode = APIC_TGM_EDGE;
LvtRegister.Vector = APIC_VECTOR_SPURIOUS; LvtRegister.Vector = APIC_VECTOR_SPURIOUS;
LvtRegister.MessageType = APIC_DM_EXTINT;
HlWriteApicRegister(APIC_LINT0, LvtRegister.Long); HlWriteApicRegister(APIC_LINT0, LvtRegister.Long);
/* Mask LINT1 */ /* Mask LINT1 */
LvtRegister.Vector = APIC_VECTOR_NMI; LvtRegister.Long = 0;
LvtRegister.Mask = 0;
LvtRegister.MessageType = APIC_DM_NMI; LvtRegister.MessageType = APIC_DM_NMI;
LvtRegister.TriggerMode = APIC_TGM_LEVEL; LvtRegister.TimerMode = 0;
LvtRegister.TriggerMode = APIC_TGM_EDGE;
LvtRegister.Vector = APIC_VECTOR_NMI;
HlWriteApicRegister(APIC_LINT1, LvtRegister.Long); HlWriteApicRegister(APIC_LINT1, LvtRegister.Long);
/* Mask ICR0 */ /* Mask ICR0 */
CommandRegister.Long0 = 0; CommandRegister.Long0 = 0;
CommandRegister.Vector = APIC_VECTOR_ZERO; CommandRegister.DestinationShortHand = APIC_DSH_Destination;
CommandRegister.MessageType = APIC_MT_INIT; CommandRegister.MessageType = APIC_MT_INIT;
CommandRegister.TriggerMode = APIC_TGM_LEVEL; CommandRegister.DestinationMode = 1;
CommandRegister.DestinationShortHand = APIC_DSH_AllIncludingSelf; CommandRegister.TriggerMode = APIC_TGM_EDGE;
CommandRegister.Vector = APIC_VECTOR_ZERO;
HlWriteApicRegister(APIC_ICR0, CommandRegister.Long0); HlWriteApicRegister(APIC_ICR0, CommandRegister.Long0);
/* Clear errors after enabling vectors */
HlWriteApicRegister(APIC_ESR, 0);
/* Register interrupt handlers once the APIC initialization is done */ /* Register interrupt handlers once the APIC initialization is done */
KeSetInterruptHandler(APIC_VECTOR_SPURIOUS, HlpHandleApicSpuriousService); KeSetInterruptHandler(APIC_VECTOR_SPURIOUS, HlpHandleApicSpuriousService);
KeSetInterruptHandler(PIC1_VECTOR_SPURIOUS, HlpHandlePicSpuriousService); KeSetInterruptHandler(PIC1_VECTOR_SPURIOUS, HlpHandlePicSpuriousService);
/* Clear errors after enabling vectors */
HlWriteApicRegister(APIC_ESR, 0);
/* Lower APIC TPR to re-enable interrupts */ /* Lower APIC TPR to re-enable interrupts */
HlWriteApicRegister(APIC_TPR, 0x00); HlWriteApicRegister(APIC_TPR, 0x00);
} }
@ -285,7 +295,7 @@ HlpInitializeLegacyPic(VOID)
/* Initialize ICW1 for PIC1 port */ /* Initialize ICW1 for PIC1 port */
Icw1.Init = TRUE; Icw1.Init = TRUE;
Icw1.InterruptMode = LevelTriggered; Icw1.InterruptMode = EdgeTriggered;
Icw1.InterruptVectorAddress = 0; Icw1.InterruptVectorAddress = 0;
Icw1.Interval = Interval8; Icw1.Interval = Interval8;
Icw1.NeedIcw4 = TRUE; Icw1.NeedIcw4 = TRUE;