UefiCpuPkg: Set up 256 IDT Descs in SEC/PEI/SMM

Currently, SEC, PEI, and SMM only set up 32 - 34 IDT
descs. This means that any exceptions received above
that number will cause a #GP fault.

This commit updates these environments to follow DXE
and set up the IDT with the architecturally defined
256 entries, each of which point to the common
exception handler.

This does two things:
- Has well defined behavior for receiving exceptions in
  these environments instead of relying on a #GP fault to
  occur.
- Allows the stack cookie interrupt (0x42) to be routed
  correctly instead of appearing as a #GP fault.

Signed-off-by: Oliver Smith-Denny <osde@microsoft.com>
This commit is contained in:
Oliver Smith-Denny 2026-02-20 12:48:56 -08:00 committed by mergify[bot]
parent 3ed9aceeb8
commit 3454d7ab41
17 changed files with 38 additions and 46 deletions

View file

@ -10,8 +10,6 @@
#include "CpuMp.h"
#include "CpuPageTable.h"
#define CPU_INTERRUPT_NUM 256
//
// Global Variables
//
@ -720,11 +718,11 @@ InitInterruptDescriptorTable (
AsmReadIdtr (&IdtDescriptor);
IdtEntryCount = (IdtDescriptor.Limit + 1) / sizeof (IA32_IDT_GATE_DESCRIPTOR);
if (IdtEntryCount < CPU_INTERRUPT_NUM) {
if (IdtEntryCount < X86_CPU_INTERRUPT_NUM) {
//
// Increase Interrupt Descriptor Table and Copy the old IDT table in
//
IdtTable = AllocateZeroPool (sizeof (IA32_IDT_GATE_DESCRIPTOR) * CPU_INTERRUPT_NUM);
IdtTable = AllocateZeroPool (sizeof (IA32_IDT_GATE_DESCRIPTOR) * X86_CPU_INTERRUPT_NUM);
ASSERT (IdtTable != NULL);
CopyMem (IdtTable, (VOID *)IdtDescriptor.Base, sizeof (IA32_IDT_GATE_DESCRIPTOR) * IdtEntryCount);
@ -732,7 +730,7 @@ InitInterruptDescriptorTable (
// Load Interrupt Descriptor Table
//
IdtDescriptor.Base = (UINTN)IdtTable;
IdtDescriptor.Limit = (UINT16)(sizeof (IA32_IDT_GATE_DESCRIPTOR) * CPU_INTERRUPT_NUM - 1);
IdtDescriptor.Limit = (UINT16)(sizeof (IA32_IDT_GATE_DESCRIPTOR) * X86_CPU_INTERRUPT_NUM - 1);
AsmWriteIdtr (&IdtDescriptor);
}

View file

@ -19,8 +19,6 @@
#include <Library/SynchronizationLib.h>
#include <Library/CpuExceptionHandlerLib.h>
#define CPU_EXCEPTION_NUM 32
#define CPU_INTERRUPT_NUM 256
#define HOOKAFTER_STUB_SIZE 18
//

View file

@ -14,10 +14,10 @@
CONST UINTN mDoFarReturnFlag = 0;
RESERVED_VECTORS_DATA mReservedVectorsData[CPU_INTERRUPT_NUM];
EFI_CPU_INTERRUPT_HANDLER mExternalInterruptHandlerTable[CPU_INTERRUPT_NUM];
RESERVED_VECTORS_DATA mReservedVectorsData[X86_CPU_INTERRUPT_NUM];
EFI_CPU_INTERRUPT_HANDLER mExternalInterruptHandlerTable[X86_CPU_INTERRUPT_NUM];
EXCEPTION_HANDLER_DATA mExceptionHandlerData = {
CPU_INTERRUPT_NUM,
X86_CPU_INTERRUPT_NUM,
0, // To be fixed
mReservedVectorsData,
mExternalInterruptHandlerTable

View file

@ -243,7 +243,7 @@ ArchSetupExceptionStack (
// Fixup TSS
//
Vector = StackSwitchExceptions[Index];
if ((Vector >= CPU_EXCEPTION_NUM) ||
if ((Vector >= X86_CPU_INTERRUPT_NUM) ||
(Vector >= (Idtr.Limit + 1) / sizeof (IA32_IDT_GATE_DESCRIPTOR)))
{
continue;

View file

@ -168,7 +168,7 @@ InitializeCpuExceptionHandlers (
EXCEPTION_HANDLER_DATA *ExceptionHandlerData;
RESERVED_VECTORS_DATA *ReservedVectors;
ReservedVectors = AllocatePool (sizeof (RESERVED_VECTORS_DATA) * CPU_EXCEPTION_NUM);
ReservedVectors = AllocatePool (sizeof (RESERVED_VECTORS_DATA) * X86_CPU_INTERRUPT_NUM);
if (ReservedVectors == NULL) {
ASSERT (ReservedVectors != NULL);
return EFI_OUT_OF_RESOURCES;
@ -181,7 +181,7 @@ InitializeCpuExceptionHandlers (
return EFI_OUT_OF_RESOURCES;
}
ExceptionHandlerData->IdtEntryCount = CPU_EXCEPTION_NUM;
ExceptionHandlerData->IdtEntryCount = X86_CPU_INTERRUPT_NUM;
ExceptionHandlerData->ReservedVectors = ReservedVectors;
ExceptionHandlerData->ExternalInterruptHandler = AllocateZeroPool (sizeof (EFI_CPU_INTERRUPT_HANDLER) * ExceptionHandlerData->IdtEntryCount);
InitializeSpinLock (&ExceptionHandlerData->DisplayMessageSpinLock);

View file

@ -134,7 +134,7 @@ CommonExceptionHandlerWorker (
(ExternalInterruptHandler[ExceptionType] != NULL))
{
(ExternalInterruptHandler[ExceptionType])(ExceptionType, SystemContext);
} else if (ExceptionType < CPU_EXCEPTION_NUM) {
} else if (ExceptionType < X86_CPU_INTERRUPT_NUM) {
//
// Get Spinlock to display CPU information
//
@ -271,7 +271,7 @@ InitializeCpuExceptionHandlersWorker (
//
// Setup the exception handlers according to IDT size, but no more than
// ExceptionHandlerData->IdtEntryCount (32 in PEI and SMM, 256 in DXE) handlers.
// ExceptionHandlerData->IdtEntryCount (256) handlers.
//
AsmReadIdtr (&IdtDescriptor);
IdtEntryCount = (IdtDescriptor.Limit + 1) / sizeof (IA32_IDT_GATE_DESCRIPTOR);

View file

@ -108,7 +108,7 @@ InitializeCpuExceptionHandlers (
)
{
EFI_STATUS Status;
RESERVED_VECTORS_DATA ReservedVectorData[CPU_EXCEPTION_NUM];
RESERVED_VECTORS_DATA ReservedVectorData[X86_CPU_INTERRUPT_NUM];
IA32_DESCRIPTOR IdtDescriptor;
UINTN IdtEntryCount;
UINT16 CodeSegment;
@ -118,8 +118,8 @@ InitializeCpuExceptionHandlers (
UINTN InterruptHandler;
if (VectorInfo != NULL) {
SetMem ((VOID *)ReservedVectorData, sizeof (RESERVED_VECTORS_DATA) * CPU_EXCEPTION_NUM, 0xff);
Status = ReadAndVerifyVectorInfo (VectorInfo, ReservedVectorData, CPU_EXCEPTION_NUM);
SetMem ((VOID *)ReservedVectorData, sizeof (RESERVED_VECTORS_DATA) * X86_CPU_INTERRUPT_NUM, 0xff);
Status = ReadAndVerifyVectorInfo (VectorInfo, ReservedVectorData, X86_CPU_INTERRUPT_NUM);
if (EFI_ERROR (Status)) {
return EFI_INVALID_PARAMETER;
}
@ -130,11 +130,11 @@ InitializeCpuExceptionHandlers (
//
AsmReadIdtr (&IdtDescriptor);
IdtEntryCount = (IdtDescriptor.Limit + 1) / sizeof (IA32_IDT_GATE_DESCRIPTOR);
if (IdtEntryCount > CPU_EXCEPTION_NUM) {
if (IdtEntryCount > X86_CPU_INTERRUPT_NUM) {
//
// CPU exception library only setup CPU_EXCEPTION_NUM exception handler at most
// CPU exception library only setup X86_CPU_INTERRUPT_NUM exception handler at most
//
IdtEntryCount = CPU_EXCEPTION_NUM;
IdtEntryCount = X86_CPU_INTERRUPT_NUM;
}
//

View file

@ -11,10 +11,10 @@
CONST UINTN mDoFarReturnFlag = 1;
RESERVED_VECTORS_DATA mReservedVectorsData[CPU_EXCEPTION_NUM];
EFI_CPU_INTERRUPT_HANDLER mExternalInterruptHandlerTable[CPU_EXCEPTION_NUM];
RESERVED_VECTORS_DATA mReservedVectorsData[X86_CPU_INTERRUPT_NUM];
EFI_CPU_INTERRUPT_HANDLER mExternalInterruptHandlerTable[X86_CPU_INTERRUPT_NUM];
EXCEPTION_HANDLER_DATA mExceptionHandlerData = {
CPU_EXCEPTION_NUM,
X86_CPU_INTERRUPT_NUM,
0, // To be fixed
mReservedVectorsData,
mExternalInterruptHandlerTable

View file

@ -54,7 +54,6 @@
#define UNIT_TEST_APP_NAME "Cpu Exception Handler Lib Unit Tests"
#define UNIT_TEST_APP_VERSION "1.0"
#define CPU_INTERRUPT_NUM 256
#define SPEC_MAX_EXCEPTION_NUM 22
#define CR4_RESERVED_BIT BIT15

View file

@ -26,10 +26,10 @@ InitializeBspIdt (
Idtr = AllocateZeroPool (sizeof (IA32_DESCRIPTOR));
ASSERT (Idtr != NULL);
NewIdtTable = AllocateZeroPool (sizeof (IA32_IDT_GATE_DESCRIPTOR) * CPU_INTERRUPT_NUM);
NewIdtTable = AllocateZeroPool (sizeof (IA32_IDT_GATE_DESCRIPTOR) * X86_CPU_INTERRUPT_NUM);
ASSERT (NewIdtTable != NULL);
Idtr->Base = (UINTN)NewIdtTable;
Idtr->Limit = (UINT16)(sizeof (IA32_IDT_GATE_DESCRIPTOR) * CPU_INTERRUPT_NUM - 1);
Idtr->Limit = (UINT16)(sizeof (IA32_IDT_GATE_DESCRIPTOR) * X86_CPU_INTERRUPT_NUM - 1);
AsmWriteIdtr (Idtr);
return Idtr;

View file

@ -27,7 +27,7 @@ InitializeBspIdt (
Idtr = AllocateZeroPool (sizeof (IA32_DESCRIPTOR));
ASSERT (Idtr != NULL);
NewIdtTable = AllocateZeroPool (sizeof (IA32_IDT_GATE_DESCRIPTOR) * CPU_INTERRUPT_NUM + sizeof (UINTN));
NewIdtTable = AllocateZeroPool (sizeof (IA32_IDT_GATE_DESCRIPTOR) * X86_CPU_INTERRUPT_NUM + sizeof (UINTN));
ASSERT (NewIdtTable != NULL);
//
// Store original PeiServicePointer before new Idt table
@ -36,7 +36,7 @@ InitializeBspIdt (
NewIdtTable = (UINTN *)((UINTN)NewIdtTable + sizeof (UINTN));
Idtr->Base = (UINTN)NewIdtTable;
Idtr->Limit = (UINT16)(sizeof (IA32_IDT_GATE_DESCRIPTOR) * CPU_INTERRUPT_NUM - 1);
Idtr->Limit = (UINT16)(sizeof (IA32_IDT_GATE_DESCRIPTOR) * X86_CPU_INTERRUPT_NUM - 1);
AsmWriteIdtr (Idtr);
return Idtr;

View file

@ -240,7 +240,7 @@ ArchSetupExceptionStack (
// Set the IST field to enable corresponding IST
//
Vector = StackSwitchExceptions[Index];
if ((Vector >= CPU_EXCEPTION_NUM) ||
if ((Vector >= X86_CPU_INTERRUPT_NUM) ||
(Vector >= (Idtr.Limit + 1) / sizeof (IA32_IDT_GATE_DESCRIPTOR)))
{
continue;

View file

@ -33,11 +33,10 @@ SECTION .text
ALIGN 8
; Generate 32 IDT vectors.
; 32 IDT vectors are enough because interrupts (32+) are not enabled in SEC and PEI phase.
; Generate 256 IDT vectors.
AsmIdtVectorBegin:
%assign Vector 0
%rep 32
%rep 256
push byte %[Vector]
push rax
mov rax, ASM_PFX(CommonInterruptEntry)
@ -390,7 +389,7 @@ global ASM_PFX(AsmGetTemplateAddressMap)
ASM_PFX(AsmGetTemplateAddressMap):
lea rax, [AsmIdtVectorBegin]
mov qword [rcx], rax
mov qword [rcx + 0x8], (AsmIdtVectorEnd - AsmIdtVectorBegin) / 32
mov qword [rcx + 0x8], (AsmIdtVectorEnd - AsmIdtVectorBegin) / 256
lea rax, [HookAfterStubHeaderBegin]
mov qword [rcx + 0x10], rax
ret

View file

@ -274,10 +274,10 @@ InitSmmIdt (
CONST EFI_PEI_SERVICES **PeiServices;
//
// There are 32 (not 255) entries in it since only processor
// generated exceptions will be handled.
// Populate 255 entries to ensure that a known state occurs
// for all possible exception vectors.
//
gcSmmInitIdtr.Limit = (sizeof (IA32_IDT_GATE_DESCRIPTOR) * 32) - 1;
gcSmmInitIdtr.Limit = (sizeof (IA32_IDT_GATE_DESCRIPTOR) * X86_CPU_INTERRUPT_NUM) - 1;
//
// Allocate for IDT.

View file

@ -105,9 +105,9 @@ SmmRestoreCpu (
//
// Setup X64 IDT table
//
ZeroMem (IdtEntryTable, sizeof (IA32_IDT_GATE_DESCRIPTOR) * 32);
ZeroMem (IdtEntryTable, sizeof (IA32_IDT_GATE_DESCRIPTOR) * X86_CPU_INTERRUPT_NUM);
X64Idtr.Base = (UINTN)IdtEntryTable;
X64Idtr.Limit = (UINT16)(sizeof (IA32_IDT_GATE_DESCRIPTOR) * 32 - 1);
X64Idtr.Limit = (UINT16)(sizeof (IA32_IDT_GATE_DESCRIPTOR) * X86_CPU_INTERRUPT_NUM - 1);
AsmWriteIdtr ((IA32_DESCRIPTOR *)&X64Idtr);
//

View file

@ -138,10 +138,10 @@ InitializeSmmIdt (
IA32_DESCRIPTOR DxeIdtr;
//
// There are 32 (not 255) entries in it since only processor
// generated exceptions will be handled.
// Populate 255 entries to ensure that a known state occurs
// for all possible exception vectors.
//
gcSmiIdtr.Limit = (sizeof (IA32_IDT_GATE_DESCRIPTOR) * 32) - 1;
gcSmiIdtr.Limit = (sizeof (IA32_IDT_GATE_DESCRIPTOR) * X86_CPU_INTERRUPT_NUM) - 1;
//
// Allocate page aligned IDT, because it might be set as read only.
//

View file

@ -12,8 +12,6 @@
#if defined (MDE_CPU_IA32) || defined (MDE_CPU_X64)
#define SEC_IDT_ENTRY_COUNT 34
typedef struct _SEC_IDT_TABLE {
//
// Reserved 8 bytes preceding IDT to store EFI_PEI_SERVICES**, since IDT base
@ -22,7 +20,7 @@ typedef struct _SEC_IDT_TABLE {
// EFI_PEI_SERVICES**
//
UINT64 PeiService;
IA32_IDT_GATE_DESCRIPTOR IdtTable[SEC_IDT_ENTRY_COUNT];
IA32_IDT_GATE_DESCRIPTOR IdtTable[X86_CPU_INTERRUPT_NUM];
} SEC_IDT_TABLE;
//
@ -218,7 +216,7 @@ SecStartup (
// |-------------------|----> TempRamBase
IdtTableInStack.PeiService = 0;
for (Index = 0; Index < SEC_IDT_ENTRY_COUNT; Index++) {
for (Index = 0; Index < X86_CPU_INTERRUPT_NUM; Index++) {
ZeroMem ((VOID *)&IdtTableInStack.IdtTable[Index], sizeof (IA32_IDT_GATE_DESCRIPTOR));
CopyMem ((VOID *)&IdtTableInStack.IdtTable[Index], (VOID *)&mIdtEntryTemplate, sizeof (UINT64));
}