[NTOS:KE]
authorThomas Faber <thomas.faber@reactos.org>
Sun, 13 Apr 2014 12:04:13 +0000 (12:04 +0000)
committerThomas Faber <thomas.faber@reactos.org>
Sun, 13 Apr 2014 12:04:13 +0000 (12:04 +0000)
- When switching to VM86 mode, ensure a 16 byte aligned floating point save area.
CORE-7581 #resolve

svn path=/trunk/; revision=62736

reactos/ntoskrnl/include/internal/i386/ke.h
reactos/ntoskrnl/ke/i386/ctxswitch.S
reactos/ntoskrnl/ke/i386/v86vdm.c

index d461a01..d6d3906 100644 (file)
@@ -557,6 +557,7 @@ FORCEINLINE
 PFX_SAVE_AREA
 KiGetThreadNpxArea(IN PKTHREAD Thread)
 {
+    ASSERT((ULONG_PTR)Thread->InitialStack % 16 == 0);
     return (PFX_SAVE_AREA)((ULONG_PTR)Thread->InitialStack - sizeof(FX_SAVE_AREA));
 }
 
index 1d0ebe4..4740342 100644 (file)
@@ -143,7 +143,7 @@ _Ki386SetupAndExitToV86Mode@4:
 
     /* Enter V8086 mode */
     pushad
-    sub esp, (12 + KTRAP_FRAME_LENGTH + NPX_FRAME_LENGTH)
+    sub esp, (12 + KTRAP_FRAME_LENGTH + NPX_FRAME_LENGTH + 16)
     mov ecx, esp
     call @KiEnterV86Mode@4
     jmp $
@@ -155,7 +155,7 @@ PUBLIC @Ki386BiosCallReturnAddress@4
     /* Exit V8086 mode */
     call @KiExitV86Mode@4
     mov esp, eax
-    add esp, (12 + KTRAP_FRAME_LENGTH + NPX_FRAME_LENGTH)
+    add esp, (12 + KTRAP_FRAME_LENGTH + NPX_FRAME_LENGTH + 16)
     popad
     ret 4
 
index 8f241be..aee9389 100644 (file)
@@ -465,6 +465,7 @@ ULONG_PTR
 FASTCALL
 KiExitV86Mode(IN PKTRAP_FRAME TrapFrame)
 {
+    ULONG_PTR StackFrameUnaligned;
     PKV8086_STACK_FRAME StackFrame;
     PKTHREAD Thread;
     PKTRAP_FRAME PmTrapFrame;
@@ -472,10 +473,12 @@ KiExitV86Mode(IN PKTRAP_FRAME TrapFrame)
     PFX_SAVE_AREA NpxFrame;
 
     /* Get the stack frame back */
-    StackFrame = CONTAINING_RECORD(TrapFrame->Esi, KV8086_STACK_FRAME, V86Frame);
+    StackFrameUnaligned = TrapFrame->Esi;
+    StackFrame = (PKV8086_STACK_FRAME)(ROUND_UP(StackFrameUnaligned - 4, 16) + 4);
     PmTrapFrame = &StackFrame->TrapFrame;
     V86Frame = &StackFrame->V86Frame;
     NpxFrame = &StackFrame->NpxArea;
+    ASSERT((ULONG_PTR)NpxFrame % 16 == 0);
 
     /* Copy the FPU frame back */
     Thread = KeGetCurrentThread();
@@ -493,18 +496,21 @@ KiExitV86Mode(IN PKTRAP_FRAME TrapFrame)
 
     /* Enable interrupts and return a pointer to the trap frame */
     _enable();
-    return (ULONG)PmTrapFrame;
+    return StackFrameUnaligned;
 }
 
 VOID
 FASTCALL
-KiEnterV86Mode(IN PKV8086_STACK_FRAME StackFrame)
+KiEnterV86Mode(IN ULONG_PTR StackFrameUnaligned)
 {
     PKTHREAD Thread;
+    PKV8086_STACK_FRAME StackFrame = (PKV8086_STACK_FRAME)(ROUND_UP(StackFrameUnaligned - 4, 16) + 4);
     PKTRAP_FRAME TrapFrame = &StackFrame->TrapFrame;
     PKV86_FRAME V86Frame = &StackFrame->V86Frame;
     PFX_SAVE_AREA NpxFrame = &StackFrame->NpxArea;
 
+    ASSERT((ULONG_PTR)NpxFrame % 16 == 0);
+
     /* Build fake user-mode trap frame */
     TrapFrame->SegCs = KGDT_R0_CODE | RPL_MASK;
     TrapFrame->SegEs = TrapFrame->SegDs = TrapFrame->SegFs = TrapFrame->SegGs = 0;
@@ -522,7 +528,7 @@ KiEnterV86Mode(IN PKV8086_STACK_FRAME StackFrame)
     TrapFrame->Eip = (ULONG_PTR)Ki386BiosCallReturnAddress;
 
     /* Save our stack (after the frames) */
-    TrapFrame->Esi = (ULONG_PTR)V86Frame;
+    TrapFrame->Esi = StackFrameUnaligned;
     TrapFrame->Edi = (ULONG_PTR)_AddressOfReturnAddress() + 4;
 
     /* Sanitize EFlags and enable interrupts */