Ring3: Fixed buggy timer interrupt handling for IA32.

This commit is contained in:
Mikhail Krichanov 2024-09-05 11:46:52 +03:00
parent 454d582450
commit be8f6f968e
4 changed files with 20 additions and 14 deletions
MdePkg/Include/Library
OvmfPkg
UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32

@ -5616,10 +5616,10 @@ typedef struct {
} IA32_DESCRIPTOR;
#pragma pack ()
#define IA32_IDT_GATE_TYPE_TASK 0x85
#define IA32_IDT_GATE_TYPE_TASK 0xE5
#define IA32_IDT_GATE_TYPE_INTERRUPT_16 0x86
#define IA32_IDT_GATE_TYPE_TRAP_16 0x87
#define IA32_IDT_GATE_TYPE_INTERRUPT_32 0x8E
#define IA32_IDT_GATE_TYPE_INTERRUPT_32 0xEE
#define IA32_IDT_GATE_TYPE_TRAP_32 0x8F
#define IA32_GDT_TYPE_TSS 0x9

@ -595,6 +595,7 @@
gEfiMdePkgTokenSpaceGuid.PcdImageProtectionPolicy|0x70000000
!endif
gEfiMdeModulePkgTokenSpaceGuid.PcdCpuStackGuard|TRUE
gEfiMdeModulePkgTokenSpaceGuid.PcdEnableUserSpace|TRUE
#
# Firmware volume supports UE, and may require PE.

@ -202,22 +202,31 @@ ArchSetupExceptionStack (
// be filled by processor during task switching.
//
TssBase = (UINTN)Tss;
//
// Last byte of bitmap must be followed by a byte with all bits set.
//
TssDesc->Uint64 = 0;
TssDesc->Bits.LimitLow = (UINT16)(sizeof (IA32_TASK_STATE_SEGMENT) + IO_BIT_MAP_SIZE - 1);
TssDesc->Bits.LimitLow = (UINT16)(sizeof (IA32_TASK_STATE_SEGMENT) + IO_BIT_MAP_SIZE - 2);
TssDesc->Bits.BaseLow = (UINT16)TssBase;
TssDesc->Bits.BaseMid = (UINT8)(TssBase >> 16);
TssDesc->Bits.Type = IA32_GDT_TYPE_TSS;
TssDesc->Bits.DPL = 3;
TssDesc->Bits.P = 1;
TssDesc->Bits.LimitHigh = (sizeof (IA32_TASK_STATE_SEGMENT) + IO_BIT_MAP_SIZE - 1) >> 16;
TssDesc->Bits.LimitHigh = (sizeof (IA32_TASK_STATE_SEGMENT) + IO_BIT_MAP_SIZE - 2) >> 16;
TssDesc->Bits.BaseHigh = (UINT8)(TssBase >> 24);
//
// Set I/O Permission Bit Map
//
ZeroMem (Tss, sizeof (*Tss));
//
// Plus 1 byte is for compact stack layout in case StackTop is already aligned.
//
StackTop = StackTop - CPU_STACK_ALIGNMENT + 1;
StackTop = (UINTN)ALIGN_POINTER (StackTop, CPU_STACK_ALIGNMENT);
Tss->ESP0 = StackTop;
Tss->SS0 = AsmReadSs ();
Tss->IOMapBaseAddress = sizeof (IA32_TASK_STATE_SEGMENT);
//
// Allow access to gUartBase = 0x3F8 and Offsets: 0x01, 0x03, 0x04, 0x05, 0x06
@ -240,11 +249,7 @@ ArchSetupExceptionStack (
// Fixup exception task descriptor and task-state segment
//
AsmGetTssTemplateMap (&TemplateMap);
//
// Plus 1 byte is for compact stack layout in case StackTop is already aligned.
//
StackTop = StackTop - CPU_STACK_ALIGNMENT + 1;
StackTop = (UINTN)ALIGN_POINTER (StackTop, CPU_STACK_ALIGNMENT);
IdtTable = (IA32_IDT_GATE_DESCRIPTOR *)Idtr.Base;
for (Index = 0; Index < CPU_STACK_SWITCH_EXCEPTION_NUMBER; ++Index, ++TssDesc, ++Tss) {
//
@ -257,6 +262,7 @@ ArchSetupExceptionStack (
TssDesc->Bits.BaseLow = (UINT16)TssBase;
TssDesc->Bits.BaseMid = (UINT8)(TssBase >> 16);
TssDesc->Bits.Type = IA32_GDT_TYPE_TSS;
TssDesc->Bits.DPL = 3;
TssDesc->Bits.P = 1;
TssDesc->Bits.LimitHigh = 0;
TssDesc->Bits.BaseHigh = (UINT8)(TssBase >> 24);

@ -208,7 +208,7 @@ ErrorCodeAndVectorOnStack:
jz sameCPL_0
mov ecx, [ecx]
sameCPL_0:
push ecx ; ESP
push ecx ; ESP
push dword [ebp] ; EBP
push esi
push edi
@ -390,7 +390,7 @@ sameCPL_1:
pop ds
pop dword [ebp + 4 * 4]
; Check whether Ring0 process was interrupted.
mov ecx, ss
mov ecx, ds
and ecx, 3
jz sameCPL_2
pop dword [ebp + 7 * 4]
@ -413,9 +413,8 @@ continue:
push ecx
mov ecx, ds
and ecx, 3
cmp ecx, 3
pop ecx
je ReturnToRing3
jnz ReturnToRing3
pop dword [ebp - 8]
pop dword [ebp - 4]