mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 01:55:19 +00:00
FPU/SSE state saving on taskswitching, FPU and SSE exception support.
svn path=/trunk/; revision=11728
This commit is contained in:
parent
ede5e4a1f9
commit
8119f6f384
21 changed files with 866 additions and 242 deletions
|
@ -5,7 +5,8 @@
|
|||
#ifndef __INCLUDE_DDK_I386_TSS_H
|
||||
#define __INCLUDE_DDK_I386_TSS_H
|
||||
|
||||
#define KTSS_ESP0 (0x4)
|
||||
#define KTSS_ESP0 (0x4)
|
||||
#define KTSS_EFLAGS (0x24)
|
||||
#define KTSS_IOMAPBASE (0x66)
|
||||
|
||||
#ifndef __ASM__
|
||||
|
|
|
@ -20,10 +20,11 @@
|
|||
#ifndef __NTOSKRNL_INCLUDE_INTERNAL_I386_FPU_H
|
||||
#define __NTOSKRNL_INCLUDE_INTERNAL_I386_FPU_H
|
||||
|
||||
extern ULONG HardwareMathSupport;
|
||||
#define SIZEOF_FX_SAVE_AREA 528
|
||||
|
||||
VOID
|
||||
KiCheckFPU(VOID);
|
||||
#ifndef __ASM__
|
||||
|
||||
#include <internal/i386/ke.h>
|
||||
|
||||
typedef struct _FNSAVE_FORMAT {
|
||||
ULONG ControlWord;
|
||||
|
@ -52,7 +53,7 @@ typedef struct _FXSAVE_FORMAT {
|
|||
UCHAR Reserved4[224];
|
||||
UCHAR Align16Byte[8];
|
||||
} FXSAVE_FORMAT, *PFXSAVE_FORMAT;
|
||||
|
||||
|
||||
typedef struct _FX_SAVE_AREA {
|
||||
union {
|
||||
FNSAVE_FORMAT FnArea;
|
||||
|
@ -62,4 +63,22 @@ typedef struct _FX_SAVE_AREA {
|
|||
ULONG Cr0NpxState;
|
||||
} FX_SAVE_AREA, *PFX_SAVE_AREA;
|
||||
|
||||
|
||||
extern ULONG HardwareMathSupport;
|
||||
|
||||
VOID
|
||||
KiCheckFPU(VOID);
|
||||
|
||||
NTSTATUS
|
||||
KiHandleFpuFault(PKTRAP_FRAME Tf, ULONG ExceptionNr);
|
||||
|
||||
VOID
|
||||
KiFloatingSaveAreaToFxSaveArea(PFX_SAVE_AREA FxSaveArea, CONST FLOATING_SAVE_AREA *FloatingSaveArea);
|
||||
|
||||
BOOL
|
||||
KiContextToFxSaveArea(PFX_SAVE_AREA FxSaveArea, PCONTEXT Context);
|
||||
|
||||
#endif /* !__ASM__ */
|
||||
|
||||
#endif /* __NTOSKRNL_INCLUDE_INTERNAL_I386_FPU_H */
|
||||
|
||||
|
|
|
@ -69,22 +69,39 @@
|
|||
#define KTRAP_FRAME_RESERVED9 (0x8A)
|
||||
#define KTRAP_FRAME_SIZE (0x8C)
|
||||
|
||||
#define X86_EFLAGS_IF 0x00000200 /* Interrupt Enable flag */
|
||||
#define X86_EFLAGS_IOPL 0x00003000 /* I/O Privilege Level bits */
|
||||
#define X86_EFLAGS_NT 0x00004000 /* Nested Task flag */
|
||||
#define X86_EFLAGS_VM 0x00020000 /* Virtual Mode */
|
||||
#define X86_EFLAGS_ID 0x00200000 /* CPUID detection flag */
|
||||
|
||||
#define X86_CR0_NE 0x00000020 /* enable native FPU error reporting */
|
||||
#define X86_CR0_TS 0x00000008 /* enable exception on FPU instruction for task switch */
|
||||
#define X86_CR0_EM 0x00000004 /* enable FPU emulation (disable FPU) */
|
||||
#define X86_CR0_MP 0x00000002 /* enable FPU monitoring */
|
||||
|
||||
#define X86_CR4_PAE 0x00000020 /* enable physical address extensions */
|
||||
#define X86_CR4_PGE 0x00000080 /* enable global pages */
|
||||
#define X86_CR4_OSFXSR 0x00000200 /* enable FXSAVE/FXRSTOR instructions */
|
||||
#define X86_CR4_OSXMMEXCPT 0x00000400 /* enable #XF exception */
|
||||
|
||||
#define X86_FEATURE_TSC 0x00000010 /* time stamp counters are present */
|
||||
#define X86_FEATURE_PAE 0x00000040 /* physical address extension is present */
|
||||
#define X86_FEATURE_CX8 0x00000100 /* CMPXCHG8B instruction present */
|
||||
#define X86_FEATURE_PGE 0x00002000 /* Page Global Enable */
|
||||
#define X86_FEATURE_MMX 0x00800000 /* MMX extension present */
|
||||
#define X86_FEATURE_FXSR 0x01000000 /* FXSAVE/FXRSTOR instructions present */
|
||||
#define X86_FEATURE_SSE 0x02000000 /* SSE extension present */
|
||||
#define X86_FEATURE_SSE2 0x04000000 /* SSE2 extension present */
|
||||
|
||||
#define X86_EXT_FEATURE_SSE3 0x00000001 /* SSE3 extension present */
|
||||
#define X86_EXT_FEATURE_3DNOW 0x40000000 /* 3DNOW! extension present */
|
||||
|
||||
/* Possible values for KTHREAD's NpxState */
|
||||
#define NPX_STATE_INVALID 0x01
|
||||
#define NPX_STATE_VALID 0x02
|
||||
#define NPX_STATE_DIRTY 0x04
|
||||
|
||||
#ifndef __ASM__
|
||||
|
||||
typedef struct _KTRAP_FRAME
|
||||
|
@ -187,12 +204,20 @@ NtEarlyInitVdm(VOID);
|
|||
: "r" (X));
|
||||
#define Ke386SaveFlags(x) __asm__ __volatile__("pushfl ; popl %0":"=g" (x): /* no input */)
|
||||
#define Ke386RestoreFlags(x) __asm__ __volatile__("pushl %0 ; popfl": /* no output */ :"g" (x):"memory")
|
||||
#define Ke386GetCr4() ({ \
|
||||
|
||||
#define _Ke386GetCr(N) ({ \
|
||||
unsigned int __d; \
|
||||
__asm__("movl %%cr4,%0\n\t" :"=r" (__d)); \
|
||||
__asm__("movl %%cr" #N ",%0\n\t" :"=r" (__d)); \
|
||||
__d; \
|
||||
})
|
||||
#define Ke386SetCr4(X) __asm__ __volatile__("movl %0,%%cr4": :"r" (X));
|
||||
#define _Ke386SetCr(N,X) __asm__ __volatile__("movl %0,%%cr" #N : :"r" (X));
|
||||
|
||||
#define Ke386GetCr0() _Ke386GetCr(0)
|
||||
#define Ke386SetCr0(X) _Ke386SetCr(0,X)
|
||||
#define Ke386GetCr2() _Ke386GetCr(2)
|
||||
#define Ke386SetCr2(X) _Ke386SetCr(2,X)
|
||||
#define Ke386GetCr4() _Ke386GetCr(4)
|
||||
#define Ke386SetCr4(X) _Ke386SetCr(4,X)
|
||||
|
||||
static inline void Ki386Cpuid(ULONG Op, PULONG Eax, PULONG Ebx, PULONG Ecx, PULONG Edx)
|
||||
{
|
||||
|
@ -207,6 +232,7 @@ static inline void Ki386Cpuid(ULONG Op, PULONG Eax, PULONG Ebx, PULONG Ecx, PULO
|
|||
|
||||
|
||||
#elif defined(_MSC_VER)
|
||||
|
||||
#define Ke386DisableInterrupts() __asm cli
|
||||
#define Ke386EnableInterrupts() __asm sti
|
||||
#define Ke386HaltProcessor() __asm hlt
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#define KTHREAD_STACK_LIMIT 0x1C
|
||||
#define KTHREAD_TEB 0x20
|
||||
#define KTHREAD_KERNEL_STACK 0x28
|
||||
#define KTHREAD_NPX_STATE 0x31
|
||||
#define KTHREAD_APCSTATE_PROCESS 0x44
|
||||
#define KTHREAD_SERVICE_TABLE 0xDC
|
||||
#define KTHREAD_PREVIOUS_MODE 0x137
|
||||
|
@ -44,6 +45,7 @@
|
|||
#define KPCR_SELF 0x1C
|
||||
#define KPCR_TSS 0x40
|
||||
#define KPCR_CURRENT_THREAD 0x124
|
||||
#define KPCR_NPX_THREAD 0x2A4
|
||||
|
||||
#ifndef __ASM__
|
||||
|
||||
|
@ -51,12 +53,12 @@
|
|||
|
||||
#pragma pack(push,4)
|
||||
|
||||
// Fixme: Use correct types?
|
||||
/* Fixme: Use correct types? */
|
||||
typedef struct _KPROCESSOR_STATE {
|
||||
PCONTEXT ContextFrame;
|
||||
PVOID SpecialRegisters;
|
||||
} KPROCESSOR_STATE;
|
||||
|
||||
|
||||
/* ProcessoR Control Block */
|
||||
typedef struct _KPRCB {
|
||||
USHORT MinorVersion;
|
||||
|
|
|
@ -27,10 +27,9 @@
|
|||
#ifndef __NTOSKRNL_INCLUDE_INTERNAL_TRAP_H
|
||||
#define __NTOSKRNL_INCLUDE_INTERNAL_TRAP_H
|
||||
|
||||
#define TF_SAVED_ORIG_STACK (0x8C)
|
||||
#define TF_REGS (0x90)
|
||||
#define TF_ORIG_EBP (0x94)
|
||||
|
||||
#define TF_SAVED_EXCEPTION_STACK (0x8C)
|
||||
#define TF_REGS (0x90)
|
||||
#define TF_ORIG_EBP (0x94)
|
||||
|
||||
#ifndef __ASM__
|
||||
|
||||
|
@ -40,7 +39,7 @@ typedef struct _KV86M_TRAP_FRAME
|
|||
{
|
||||
KTRAP_FRAME Tf;
|
||||
|
||||
ULONG SavedInitialStack;
|
||||
ULONG SavedExceptionStack;
|
||||
|
||||
/*
|
||||
* These are put on the top of the stack by the routine that entered
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include <ddk/kefuncs.h>
|
||||
#include <ddk/pnptypes.h>
|
||||
#include <ddk/pnpfuncs.h>
|
||||
#include <ntdll/ldr.h>
|
||||
#include <internal/ctype.h>
|
||||
#include <internal/ntoskrnl.h>
|
||||
#include <internal/id.h>
|
||||
|
@ -55,7 +56,6 @@
|
|||
#include <internal/trap.h>
|
||||
#include <internal/safe.h>
|
||||
#include <internal/test.h>
|
||||
#include <ntdll/ldr.h>
|
||||
#include <napi/core.h>
|
||||
#include <napi/dbg.h>
|
||||
#include <napi/teb.h>
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
/* $Id: bthread.S,v 1.10 2004/10/31 19:46:10 ekohl Exp $
|
||||
/* $Id: bthread.S,v 1.11 2004/11/20 23:46:36 blight Exp $
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
|
@ -141,18 +141,6 @@ _PsBeginThreadWithContextInternal:
|
|||
addl $24, %esp
|
||||
.L3:
|
||||
|
||||
/*
|
||||
* Load the floating point registers
|
||||
*/
|
||||
movl (_HardwareMathSupport), %eax
|
||||
testl %eax,%eax
|
||||
jz .L2
|
||||
testl $(CONTEXT_FLOATING_POINT & ~CONTEXT_i386), %ebx
|
||||
jz .L2
|
||||
frstor (%esp)
|
||||
.L2:
|
||||
addl $112, %esp
|
||||
|
||||
/* Load the rest of the thread's user mode context. */
|
||||
movl $0, %eax
|
||||
jmp KeReturnFromSystemCallWithHook
|
||||
|
|
|
@ -40,6 +40,10 @@
|
|||
#define _STR(x) #x
|
||||
#define STR(x) _STR(x)
|
||||
|
||||
#ifndef ARRAY_SIZE
|
||||
# define ARRAY_SIZE(x) (sizeof (x) / sizeof (x[0]))
|
||||
#endif
|
||||
|
||||
extern void interrupt_handler2e(void);
|
||||
extern void interrupt_handler2d(void);
|
||||
|
||||
|
@ -60,6 +64,9 @@ extern VOID KiTrap13(VOID);
|
|||
extern VOID KiTrap14(VOID);
|
||||
extern VOID KiTrap15(VOID);
|
||||
extern VOID KiTrap16(VOID);
|
||||
extern VOID KiTrap17(VOID);
|
||||
extern VOID KiTrap18(VOID);
|
||||
extern VOID KiTrap19(VOID);
|
||||
extern VOID KiTrapUnknown(VOID);
|
||||
|
||||
extern ULONG init_stack;
|
||||
|
@ -84,9 +91,11 @@ static char *ExceptionTypeStrings[] =
|
|||
"Stack Segment Fault",
|
||||
"General Protection",
|
||||
"Page Fault",
|
||||
"Reserved(15)",
|
||||
"Math Fault",
|
||||
"Alignment Check",
|
||||
"Machine Check"
|
||||
"Machine Check",
|
||||
"SIMD Fault"
|
||||
};
|
||||
|
||||
static NTSTATUS ExceptionToNtStatus[] =
|
||||
|
@ -106,9 +115,11 @@ static NTSTATUS ExceptionToNtStatus[] =
|
|||
STATUS_STACK_OVERFLOW,
|
||||
STATUS_ACCESS_VIOLATION,
|
||||
STATUS_ACCESS_VIOLATION,
|
||||
STATUS_ACCESS_VIOLATION, /* RESERVED */
|
||||
STATUS_ACCESS_VIOLATION, /* STATUS_FLT_INVALID_OPERATION */
|
||||
STATUS_DATATYPE_MISALIGNMENT,
|
||||
STATUS_ACCESS_VIOLATION
|
||||
STATUS_ACCESS_VIOLATION,
|
||||
STATUS_ACCESS_VIOLATION /* STATUS_FLT_MULTIPLE_TRAPS? */
|
||||
};
|
||||
|
||||
/* FUNCTIONS ****************************************************************/
|
||||
|
@ -167,7 +178,7 @@ KiKernelTrapHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr, PVOID Cr2)
|
|||
}
|
||||
else
|
||||
{
|
||||
if (ExceptionNr < 16)
|
||||
if (ExceptionNr < ARRAY_SIZE(ExceptionToNtStatus))
|
||||
{
|
||||
Er.ExceptionCode = ExceptionToNtStatus[ExceptionNr];
|
||||
}
|
||||
|
@ -190,7 +201,7 @@ KiKernelTrapHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr, PVOID Cr2)
|
|||
ULONG
|
||||
KiDoubleFaultHandler(VOID)
|
||||
{
|
||||
unsigned int cr2_;
|
||||
unsigned int cr2;
|
||||
ULONG StackLimit;
|
||||
ULONG StackBase;
|
||||
ULONG Esp0;
|
||||
|
@ -211,15 +222,7 @@ KiDoubleFaultHandler(VOID)
|
|||
Esp0 = OldTss->Esp;
|
||||
|
||||
/* Get CR2 */
|
||||
#if defined(__GNUC__)
|
||||
__asm__("movl %%cr2,%0\n\t" : "=d" (cr2_));
|
||||
#elif defined(_MSC_VER)
|
||||
__asm mov eax, cr2;
|
||||
__asm mov cr2_, eax;
|
||||
#else
|
||||
#error Unknown compiler for inline assembler
|
||||
#endif
|
||||
|
||||
cr2 = Ke386GetCr2();
|
||||
if (PsGetCurrentThread() != NULL &&
|
||||
PsGetCurrentThread()->ThreadsProcess != NULL)
|
||||
{
|
||||
|
@ -245,7 +248,7 @@ KiDoubleFaultHandler(VOID)
|
|||
/*
|
||||
* Print out the CPU registers
|
||||
*/
|
||||
if (ExceptionNr < 19)
|
||||
if (ExceptionNr < ARRAY_SIZE(ExceptionTypeStrings))
|
||||
{
|
||||
DbgPrint("%s Exception: %d(%x)\n", ExceptionTypeStrings[ExceptionNr],
|
||||
ExceptionNr, 0);
|
||||
|
@ -257,7 +260,7 @@ KiDoubleFaultHandler(VOID)
|
|||
DbgPrint("CS:EIP %x:%x ", OldTss->Cs, OldTss->Eip);
|
||||
KeRosPrintAddress((PVOID)OldTss->Eip);
|
||||
DbgPrint("\n");
|
||||
DbgPrint("cr2 %x cr3 %x ", cr2_, OldCr3);
|
||||
DbgPrint("cr2 %x cr3 %x ", cr2, OldCr3);
|
||||
DbgPrint("Proc: %x ",PsGetCurrentProcess());
|
||||
if (PsGetCurrentProcess() != NULL)
|
||||
{
|
||||
|
@ -420,7 +423,7 @@ KiDumpTrapFrame(PKTRAP_FRAME Tf, ULONG Parameter1, ULONG Parameter2)
|
|||
/*
|
||||
* Print out the CPU registers
|
||||
*/
|
||||
if (ExceptionNr < 19)
|
||||
if (ExceptionNr < ARRAY_SIZE(ExceptionTypeStrings))
|
||||
{
|
||||
DbgPrint("%s Exception: %d(%x)\n", ExceptionTypeStrings[ExceptionNr],
|
||||
ExceptionNr, Tf->ErrorCode&0xffff);
|
||||
|
@ -529,7 +532,7 @@ KiTrapHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr)
|
|||
* Complete CPU context
|
||||
*/
|
||||
{
|
||||
unsigned int cr2_;
|
||||
unsigned int cr2;
|
||||
NTSTATUS Status;
|
||||
ULONG Esp0;
|
||||
|
||||
|
@ -540,22 +543,15 @@ KiTrapHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr)
|
|||
Esp0 = (ULONG)&Tf->Eip;
|
||||
|
||||
/* Get CR2 */
|
||||
#if defined(__GNUC__)
|
||||
__asm__("movl %%cr2,%0\n\t" : "=d" (cr2_));
|
||||
#elif defined(_MSC_VER)
|
||||
__asm mov eax, cr2;
|
||||
__asm mov cr2_, eax;
|
||||
#else
|
||||
#error Unknown compiler for inline assembler
|
||||
#endif
|
||||
Tf->DebugPointer = (PVOID)cr2_;
|
||||
cr2 = Ke386GetCr2();
|
||||
Tf->DebugPointer = (PVOID)cr2;
|
||||
|
||||
/*
|
||||
* If this was a V86 mode exception then handle it specially
|
||||
*/
|
||||
if (Tf->Eflags & (1 << 17))
|
||||
{
|
||||
return(KeV86Exception(ExceptionNr, Tf, cr2_));
|
||||
return(KeV86Exception(ExceptionNr, Tf, cr2));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -574,7 +570,7 @@ KiTrapHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr)
|
|||
*/
|
||||
if (ExceptionNr == 14)
|
||||
{
|
||||
if (Ke386NoExecute && Tf->ErrorCode & 0x10 && cr2_ >= KERNEL_BASE)
|
||||
if (Ke386NoExecute && Tf->ErrorCode & 0x10 && cr2 >= KERNEL_BASE)
|
||||
{
|
||||
KEBUGCHECKWITHTF(ATTEMPTED_EXECUTE_OF_NOEXECUTE_MEMORY, 0, 0, 0, 0, Tf);
|
||||
}
|
||||
|
@ -585,7 +581,7 @@ KiTrapHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr)
|
|||
Status = MmPageFault(Tf->Cs&0xffff,
|
||||
&Tf->Eip,
|
||||
&Tf->Eax,
|
||||
cr2_,
|
||||
cr2,
|
||||
Tf->ErrorCode);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
|
@ -605,16 +601,28 @@ KiTrapHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr)
|
|||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Try to handle device-not-present, math-fault and xmm-fault exceptions.
|
||||
*/
|
||||
if (ExceptionNr == 7 || ExceptionNr == 16 || ExceptionNr == 19)
|
||||
{
|
||||
Status = KiHandleFpuFault(Tf, ExceptionNr);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle user exceptions differently
|
||||
*/
|
||||
if ((Tf->Cs & 0xFFFF) == USER_CS)
|
||||
{
|
||||
return(KiUserTrapHandler(Tf, ExceptionNr, (PVOID)cr2_));
|
||||
return(KiUserTrapHandler(Tf, ExceptionNr, (PVOID)cr2));
|
||||
}
|
||||
else
|
||||
{
|
||||
return(KiKernelTrapHandler(Tf, ExceptionNr, (PVOID)cr2_));
|
||||
return(KiKernelTrapHandler(Tf, ExceptionNr, (PVOID)cr2));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -728,11 +736,14 @@ KeInitExceptions(VOID)
|
|||
set_interrupt_gate(14, (ULONG)KiTrap14);
|
||||
set_trap_gate(15, (ULONG)KiTrap15, 0);
|
||||
set_trap_gate(16, (ULONG)KiTrap16, 0);
|
||||
set_trap_gate(17, (ULONG)KiTrap17, 0);
|
||||
set_trap_gate(18, (ULONG)KiTrap18, 0);
|
||||
set_trap_gate(19, (ULONG)KiTrap19, 0);
|
||||
|
||||
for (i=17;i<256;i++)
|
||||
{
|
||||
set_trap_gate(i,(int)KiTrapUnknown, 0);
|
||||
}
|
||||
for (i = 20; i < 256; i++)
|
||||
{
|
||||
set_trap_gate(i,(int)KiTrapUnknown, 0);
|
||||
}
|
||||
|
||||
set_system_call_gate(0x2d,(int)interrupt_handler2d);
|
||||
set_system_call_gate(0x2e,(int)interrupt_handler2e);
|
||||
|
@ -746,14 +757,14 @@ NTSTATUS STDCALL
|
|||
KeRaiseUserException(IN NTSTATUS ExceptionCode)
|
||||
{
|
||||
/* FIXME: This needs SEH */
|
||||
ULONG OldEip;
|
||||
PKTHREAD Thread = KeGetCurrentThread();
|
||||
ULONG OldEip;
|
||||
PKTHREAD Thread = KeGetCurrentThread();
|
||||
|
||||
ProbeForWrite(&Thread->Teb->ExceptionCode, sizeof(NTSTATUS), sizeof(NTSTATUS)); /* NT doesn't check this -- bad? */
|
||||
OldEip = Thread->TrapFrame->Eip;
|
||||
Thread->TrapFrame->Eip = (ULONG_PTR)LdrpGetSystemDllRaiseExceptionDispatcher();
|
||||
Thread->Teb->ExceptionCode = ExceptionCode;
|
||||
return((NTSTATUS)OldEip);
|
||||
ProbeForWrite(&Thread->Teb->ExceptionCode, sizeof(NTSTATUS), sizeof(NTSTATUS)); /* NT doesn't check this -- bad? */
|
||||
OldEip = Thread->TrapFrame->Eip;
|
||||
Thread->TrapFrame->Eip = (ULONG_PTR)LdrpGetSystemDllRaiseExceptionDispatcher();
|
||||
Thread->Teb->ExceptionCode = ExceptionCode;
|
||||
return((NTSTATUS)OldEip);
|
||||
}
|
||||
|
||||
VOID
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id: fpu.c,v 1.13 2004/08/15 16:39:05 chorns Exp $
|
||||
/* $Id: fpu.c,v 1.14 2004/11/20 23:46:36 blight Exp $
|
||||
*
|
||||
* ReactOS kernel
|
||||
* Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
|
||||
|
@ -32,71 +32,310 @@
|
|||
#define NDEBUG
|
||||
#include <internal/debug.h>
|
||||
|
||||
/* DEFINES *******************************************************************/
|
||||
|
||||
#define EXCEPTION_FLT_DENORMAL_OPERAND (0xc000008dL)
|
||||
#define EXCEPTION_FLT_DIVIDE_BY_ZERO (0xc000008eL)
|
||||
#define EXCEPTION_FLT_INEXACT_RESULT (0xc000008fL)
|
||||
#define EXCEPTION_FLT_INVALID_OPERATION (0xc0000090L)
|
||||
#define EXCEPTION_FLT_OVERFLOW (0xc0000091L)
|
||||
#define EXCEPTION_FLT_STACK_CHECK (0xc0000092L)
|
||||
#define EXCEPTION_FLT_UNDERFLOW (0xc0000093L)
|
||||
#define EXCEPTION_FLT_MULTIPLE_FAULTS (0xC00002B4L)
|
||||
#define EXCEPTION_FLT_MULTIPLE_TRAPS (0xC00002B5L)
|
||||
|
||||
/* x87 Status Word exception flags */
|
||||
#define X87_SW_IE (1<<0) /* Invalid Operation */
|
||||
#define X87_SW_DE (1<<1) /* Denormalized Operand */
|
||||
#define X87_SW_ZE (1<<2) /* Zero Devide */
|
||||
#define X87_SW_OE (1<<3) /* Overflow */
|
||||
#define X87_SW_UE (1<<4) /* Underflow */
|
||||
#define X87_SW_PE (1<<5) /* Precision */
|
||||
#define X87_SW_SE (1<<6) /* Stack Fault */
|
||||
|
||||
#define X87_SW_ES (1<<7) /* Error Summary */
|
||||
|
||||
/* MXCSR exception flags */
|
||||
#define MXCSR_IE (1<<0) /* Invalid Operation */
|
||||
#define MXCSR_DE (1<<1) /* Denormalized Operand */
|
||||
#define MXCSR_ZE (1<<2) /* Zero Devide */
|
||||
#define MXCSR_OE (1<<3) /* Overflow */
|
||||
#define MXCSR_UE (1<<4) /* Underflow */
|
||||
#define MXCSR_PE (1<<5) /* Precision */
|
||||
#define MXCSR_DAZ (1<<6) /* Denormals Are Zeros (P4 only) */
|
||||
|
||||
/* GLOBALS *******************************************************************/
|
||||
|
||||
ULONG HardwareMathSupport;
|
||||
ULONG HardwareMathSupport = 0;
|
||||
static ULONG MxcsrFeatureMask = 0, FxsrSupport = 0, XmmSupport = 0;
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
STATIC USHORT
|
||||
KiTagWordFnsaveToFxsave(USHORT TagWord)
|
||||
{
|
||||
INT tmp;
|
||||
|
||||
/*
|
||||
* Converts the tag-word. 11 (Empty) is converted into 0, everything else into 1
|
||||
*/
|
||||
tmp = ~TagWord; /* Empty is now 00, any 2 bits containing 1 mean valid */
|
||||
tmp = (tmp | (tmp >> 1)) & 0x5555; /* 0V0V0V0V0V0V0V0V */
|
||||
tmp = (tmp | (tmp >> 1)) & 0x3333; /* 00VV00VV00VV00VV */
|
||||
tmp = (tmp | (tmp >> 2)) & 0x0f0f; /* 0000VVVV0000VVVV */
|
||||
tmp = (tmp | (tmp >> 4)) & 0x00ff; /* 00000000VVVVVVVV */
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
STATIC USHORT
|
||||
KiTagWordFxsaveToFnsave(PFXSAVE_FORMAT FxSave)
|
||||
{
|
||||
USHORT TagWord = 0;
|
||||
UCHAR Tag;
|
||||
INT i;
|
||||
struct FPREG { USHORT Significand[4]; USHORT Exponent; } *FpReg;
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
if (FxSave->TagWord & (1 << i)) /* valid */
|
||||
{
|
||||
FpReg = (struct FPREG *)(FxSave->RegisterArea + (i * 16));
|
||||
switch (FpReg->Exponent & 0x00007fff)
|
||||
{
|
||||
case 0x0000:
|
||||
if (FpReg->Significand[0] == 0 && FpReg->Significand[1] == 0 &&
|
||||
FpReg->Significand[2] == 0 && FpReg->Significand[3] == 0)
|
||||
{
|
||||
Tag = 1; /* Zero */
|
||||
}
|
||||
else
|
||||
{
|
||||
Tag = 2; /* Special */
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x7fff:
|
||||
Tag = 2; /* Special */
|
||||
break;
|
||||
|
||||
default:
|
||||
if (FpReg->Significand[3] & 0x00008000)
|
||||
{
|
||||
Tag = 0; /* Valid */
|
||||
}
|
||||
else
|
||||
{
|
||||
Tag = 2; /* Special */
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
else /* empty */
|
||||
{
|
||||
Tag = 3;
|
||||
}
|
||||
TagWord |= Tag << (i * 2);
|
||||
}
|
||||
|
||||
return TagWord;
|
||||
}
|
||||
|
||||
STATIC VOID
|
||||
KiFnsaveToFxsaveFormat(PFXSAVE_FORMAT FxSave, CONST PFNSAVE_FORMAT FnSave)
|
||||
{
|
||||
INT i;
|
||||
|
||||
FxSave->ControlWord = (USHORT)FnSave->ControlWord;
|
||||
FxSave->StatusWord = (USHORT)FnSave->StatusWord;
|
||||
FxSave->TagWord = KiTagWordFnsaveToFxsave((USHORT)FnSave->TagWord);
|
||||
FxSave->ErrorOpcode = (USHORT)(FnSave->ErrorSelector >> 16);
|
||||
FxSave->ErrorOffset = FnSave->ErrorOffset;
|
||||
FxSave->ErrorSelector = FnSave->ErrorSelector & 0x0000ffff;
|
||||
FxSave->DataOffset = FnSave->DataOffset;
|
||||
FxSave->DataSelector = FnSave->DataSelector & 0x0000ffff;
|
||||
if (XmmSupport)
|
||||
FxSave->MXCsr = 0x00001f80 & MxcsrFeatureMask;
|
||||
else
|
||||
FxSave->MXCsr = 0;
|
||||
FxSave->MXCsrMask = MxcsrFeatureMask;
|
||||
memset(FxSave->Reserved3, 0, sizeof(FxSave->Reserved3) +
|
||||
sizeof(FxSave->Reserved4)); /* XXX - doesnt zero Align16Byte because
|
||||
Context->ExtendedRegisters is only 512 bytes, not 520 */
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
memcpy(FxSave->RegisterArea + (i * 16), FnSave->RegisterArea + (i * 10), 10);
|
||||
memset(FxSave->RegisterArea + (i * 16) + 10, 0, 6);
|
||||
}
|
||||
}
|
||||
|
||||
STATIC VOID
|
||||
KiFxsaveToFnsaveFormat(PFNSAVE_FORMAT FnSave, CONST PFXSAVE_FORMAT FxSave)
|
||||
{
|
||||
INT i;
|
||||
|
||||
FnSave->ControlWord = 0xffff0000 | FxSave->ControlWord;
|
||||
FnSave->StatusWord = 0xffff0000 | FxSave->StatusWord;
|
||||
FnSave->TagWord = 0xffff0000 | KiTagWordFxsaveToFnsave(FxSave);
|
||||
FnSave->ErrorOffset = FxSave->ErrorOffset;
|
||||
FnSave->ErrorSelector = FxSave->ErrorSelector & 0x0000ffff;
|
||||
FnSave->ErrorSelector |= FxSave->ErrorOpcode << 16;
|
||||
FnSave->DataOffset = FxSave->DataOffset;
|
||||
FnSave->DataSelector = FxSave->DataSelector | 0xffff0000;
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
memcpy(FnSave->RegisterArea + (i * 10), FxSave->RegisterArea + (i * 16), 10);
|
||||
}
|
||||
}
|
||||
|
||||
VOID
|
||||
KiFloatingSaveAreaToFxSaveArea(PFX_SAVE_AREA FxSaveArea, CONST FLOATING_SAVE_AREA *FloatingSaveArea)
|
||||
{
|
||||
if (FxsrSupport)
|
||||
{
|
||||
KiFnsaveToFxsaveFormat(&FxSaveArea->U.FxArea, (PFNSAVE_FORMAT)FloatingSaveArea);
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(&FxSaveArea->U.FnArea, FloatingSaveArea, sizeof(FxSaveArea->U.FnArea));
|
||||
}
|
||||
FxSaveArea->NpxSavedCpu = 0;
|
||||
FxSaveArea->Cr0NpxState = FloatingSaveArea->Cr0NpxState;
|
||||
}
|
||||
|
||||
BOOL
|
||||
KiContextToFxSaveArea(PFX_SAVE_AREA FxSaveArea, PCONTEXT Context)
|
||||
{
|
||||
BOOL FpuContextChanged = FALSE;
|
||||
|
||||
/* First of all convert the FLOATING_SAVE_AREA into the FX_SAVE_AREA */
|
||||
if ((Context->ContextFlags & CONTEXT_FLOATING_POINT) == CONTEXT_FLOATING_POINT)
|
||||
{
|
||||
KiFloatingSaveAreaToFxSaveArea(FxSaveArea, &Context->FloatSave);
|
||||
FpuContextChanged = TRUE;
|
||||
}
|
||||
|
||||
/* Now merge the FX_SAVE_AREA from the context with the destination area */
|
||||
if ((Context->ContextFlags & CONTEXT_EXTENDED_REGISTERS) == CONTEXT_EXTENDED_REGISTERS)
|
||||
{
|
||||
if (FxsrSupport)
|
||||
{
|
||||
PFXSAVE_FORMAT src = (PFXSAVE_FORMAT)Context->ExtendedRegisters;
|
||||
PFXSAVE_FORMAT dst = &FxSaveArea->U.FxArea;
|
||||
dst->MXCsr = src->MXCsr & MxcsrFeatureMask;
|
||||
memcpy(dst->Reserved3, src->Reserved3,
|
||||
sizeof(src->Reserved3) + sizeof(src->Reserved4));
|
||||
|
||||
if ((Context->ContextFlags & CONTEXT_FLOATING_POINT) != CONTEXT_FLOATING_POINT)
|
||||
{
|
||||
dst->ControlWord = src->ControlWord;
|
||||
dst->StatusWord = src->StatusWord;
|
||||
dst->TagWord = src->TagWord;
|
||||
dst->ErrorOpcode = src->ErrorOpcode;
|
||||
dst->ErrorOffset = src->ErrorOffset;
|
||||
dst->ErrorSelector = src->ErrorSelector;
|
||||
dst->DataOffset = src->DataOffset;
|
||||
dst->DataSelector = src->DataSelector;
|
||||
memcpy(dst->RegisterArea, src->RegisterArea, sizeof(src->RegisterArea));
|
||||
|
||||
FxSaveArea->NpxSavedCpu = 0;
|
||||
FxSaveArea->Cr0NpxState = 0;
|
||||
}
|
||||
FpuContextChanged = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return FpuContextChanged;
|
||||
}
|
||||
|
||||
VOID INIT_FUNCTION
|
||||
KiCheckFPU(VOID)
|
||||
{
|
||||
unsigned short int status;
|
||||
int cr0_;
|
||||
|
||||
HardwareMathSupport = 0;
|
||||
|
||||
#if defined(__GNUC__)
|
||||
__asm__("movl %%cr0, %0\n\t" : "=a" (cr0_));
|
||||
/* Set NE and MP. */
|
||||
cr0_ = cr0_ | 0x22;
|
||||
/* Clear EM */
|
||||
cr0_ = cr0_ & (~0x4);
|
||||
__asm__("movl %0, %%cr0\n\t" : : "a" (cr0_));
|
||||
int cr0;
|
||||
ULONG Flags;
|
||||
PKPCR Pcr = KeGetCurrentKPCR();
|
||||
|
||||
__asm__("clts\n\t");
|
||||
__asm__("fninit\n\t");
|
||||
__asm__("fstsw %0\n\t" : "=a" (status));
|
||||
if (status != 0)
|
||||
{
|
||||
__asm__("movl %%cr0, %0\n\t" : "=a" (cr0_));
|
||||
/* Set the EM flag in CR0 so any FPU instructions cause a trap. */
|
||||
cr0_ = cr0_ | 0x4;
|
||||
__asm__("movl %0, %%cr0\n\t" :
|
||||
: "a" (cr0_));
|
||||
return;
|
||||
}
|
||||
/* fsetpm for i287, ignored by i387 */
|
||||
__asm__(".byte 0xDB, 0xE4\n\t");
|
||||
Ke386SaveFlags(Flags);
|
||||
Ke386DisableInterrupts();
|
||||
|
||||
HardwareMathSupport = 0;
|
||||
FxsrSupport = 0;
|
||||
XmmSupport = 0;
|
||||
|
||||
cr0 = Ke386GetCr0();
|
||||
cr0 |= X86_CR0_NE | X86_CR0_MP;
|
||||
cr0 &= ~(X86_CR0_EM | X86_CR0_TS);
|
||||
Ke386SetCr0(cr0);
|
||||
|
||||
#if defined(__GNUC__)
|
||||
asm volatile("fninit\n\t");
|
||||
asm volatile("fstsw %0\n\t" : "=a" (status));
|
||||
#elif defined(_MSC_VER)
|
||||
__asm mov eax, cr0;
|
||||
__asm mov cr0_, eax;
|
||||
cr0_ |= 0x22; /* Set NE and MP. */
|
||||
cr0_ &= ~0x4; /* Clear EM */
|
||||
__asm
|
||||
{
|
||||
mov eax, cr0_;
|
||||
mov cr0, eax;
|
||||
clts;
|
||||
fninit;
|
||||
fstsw status
|
||||
}
|
||||
#else
|
||||
#error Unknown compiler for inline assembler
|
||||
#endif
|
||||
|
||||
if (status != 0)
|
||||
{
|
||||
__asm mov eax, cr0_;
|
||||
__asm or eax, 4; /* Set the EM flag in CR0 so any FPU instructions cause a trap. */
|
||||
__asm mov cr0, eax;
|
||||
/* Set the EM flag in CR0 so any FPU instructions cause a trap. */
|
||||
Ke386SetCr0(Ke386GetCr0() | X86_CR0_EM);
|
||||
Ke386RestoreFlags(Flags);
|
||||
return;
|
||||
}
|
||||
|
||||
/* fsetpm for i287, ignored by i387 */
|
||||
#if defined(__GNUC__)
|
||||
asm volatile(".byte 0xDB, 0xE4\n\t");
|
||||
#elif defined(_MSC_VER)
|
||||
__asm _emit 0xDB __asm _emit 0xe4
|
||||
// __asm fsetpm;
|
||||
// __asm__(".byte 0xDB, 0xE4\n\t");
|
||||
#else
|
||||
#error Unknown compiler for inline assembler
|
||||
#endif
|
||||
|
||||
HardwareMathSupport = 1;
|
||||
|
||||
/* check for and enable MMX/SSE support if possible */
|
||||
if ((Pcr->PrcbData.FeatureBits & X86_FEATURE_FXSR) != 0)
|
||||
{
|
||||
BYTE DummyArea[sizeof(FX_SAVE_AREA) + 15];
|
||||
PFX_SAVE_AREA FxSaveArea;
|
||||
|
||||
/* enable FXSR */
|
||||
FxsrSupport = 1;
|
||||
|
||||
/* we need a 16 byte aligned FX_SAVE_AREA */
|
||||
FxSaveArea = (PFX_SAVE_AREA)DummyArea;
|
||||
if ((ULONG_PTR)FxSaveArea & 0x0f)
|
||||
{
|
||||
FxSaveArea = (PFX_SAVE_AREA)(((ULONG_PTR)FxSaveArea + 0x10) & (~0x0f));
|
||||
}
|
||||
|
||||
Ke386SetCr4(Ke386GetCr4() | X86_CR4_OSFXSR);
|
||||
memset(&FxSaveArea->U.FxArea, 0, sizeof(FxSaveArea->U.FxArea));
|
||||
asm volatile("fxsave %0" : : "m"(FxSaveArea->U.FxArea));
|
||||
MxcsrFeatureMask = FxSaveArea->U.FxArea.MXCsrMask;
|
||||
if (MxcsrFeatureMask == 0)
|
||||
{
|
||||
MxcsrFeatureMask = 0x0000ffbf;
|
||||
}
|
||||
}
|
||||
/* FIXME: Check for SSE3 in Ke386CpuidFlags2! */
|
||||
if (Pcr->PrcbData.FeatureBits & (X86_FEATURE_SSE | X86_FEATURE_SSE2))
|
||||
{
|
||||
Ke386SetCr4(Ke386GetCr4() | X86_CR4_OSXMMEXCPT);
|
||||
|
||||
/* enable SSE */
|
||||
XmmSupport = 1;
|
||||
}
|
||||
|
||||
Ke386SetCr0(Ke386GetCr0() | X86_CR0_TS);
|
||||
Ke386RestoreFlags(Flags);
|
||||
}
|
||||
|
||||
/* This is a rather naive implementation of Ke(Save/Restore)FloatingPointState
|
||||
|
@ -109,6 +348,14 @@ KeSaveFloatingPointState(OUT PKFLOATING_SAVE Save)
|
|||
{
|
||||
char *FpState;
|
||||
|
||||
ASSERT_IRQL(DISPATCH_LEVEL); /* FIXME: is this removed for non-debug builds? I hope not! */
|
||||
|
||||
/* check if we are doing software emulation */
|
||||
if (!HardwareMathSupport)
|
||||
{
|
||||
return STATUS_ILLEGAL_FLOAT_CONTEXT;
|
||||
}
|
||||
|
||||
FpState = ExAllocatePool(PagedPool, FPU_STATE_SIZE);
|
||||
if (NULL == FpState)
|
||||
{
|
||||
|
@ -117,7 +364,7 @@ KeSaveFloatingPointState(OUT PKFLOATING_SAVE Save)
|
|||
*((PVOID *) Save) = FpState;
|
||||
|
||||
#if defined(__GNUC__)
|
||||
__asm__("fsave %0\n\t" : "=m" (*FpState));
|
||||
asm volatile("fsave %0\n\t" : "=m" (*FpState));
|
||||
#elif defined(_MSC_VER)
|
||||
__asm mov eax, FpState;
|
||||
__asm fsave [eax];
|
||||
|
@ -125,6 +372,8 @@ KeSaveFloatingPointState(OUT PKFLOATING_SAVE Save)
|
|||
#error Unknown compiler for inline assembler
|
||||
#endif
|
||||
|
||||
KeGetCurrentThread()->NpxIrql = KeGetCurrentIrql();
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -133,6 +382,11 @@ KeRestoreFloatingPointState(IN PKFLOATING_SAVE Save)
|
|||
{
|
||||
char *FpState = *((PVOID *) Save);
|
||||
|
||||
if (KeGetCurrentThread()->NpxIrql != KeGetCurrentIrql())
|
||||
{
|
||||
KEBUGCHECK(UNDEFINED_BUG_CODE);
|
||||
}
|
||||
|
||||
#if defined(__GNUC__)
|
||||
__asm__("frstor %0\n\t" : "=m" (*FpState));
|
||||
#elif defined(_MSC_VER)
|
||||
|
@ -146,3 +400,198 @@ KeRestoreFloatingPointState(IN PKFLOATING_SAVE Save)
|
|||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
KiHandleFpuFault(PKTRAP_FRAME Tf, ULONG ExceptionNr)
|
||||
{
|
||||
if (ExceptionNr == 7) /* device not present */
|
||||
{
|
||||
unsigned int cr0 = Ke386GetCr0();
|
||||
PKTHREAD CurrentThread, NpxThread;
|
||||
PFX_SAVE_AREA FxSaveArea;
|
||||
KIRQL oldIrql;
|
||||
|
||||
ASSERT((cr0 & X86_CR0_TS) == X86_CR0_TS);
|
||||
ASSERT((Tf->Eflags & X86_EFLAGS_VM) == 0);
|
||||
ASSERT((cr0 & X86_CR0_EM) == 0);
|
||||
|
||||
/* disable scheduler, clear TS in cr0 */
|
||||
ASSERT_IRQL(DISPATCH_LEVEL);
|
||||
KeRaiseIrql(DISPATCH_LEVEL, &oldIrql);
|
||||
asm volatile("clts");
|
||||
|
||||
CurrentThread = KeGetCurrentThread();
|
||||
NpxThread = KeGetCurrentKPCR()->PrcbData.NpxThread;
|
||||
|
||||
ASSERT(CurrentThread != NULL);
|
||||
DPRINT("Device not present exception happened! (Cr0 = 0x%x, NpxState = 0x%x)\n", Ke386GetCr0(), CurrentThread->NpxState);
|
||||
|
||||
/* check if the current thread already owns the FPU */
|
||||
if (NpxThread != CurrentThread) /* FIXME: maybe this could be an assertation */
|
||||
{
|
||||
BOOL FpuInitialized = FALSE;
|
||||
/* save the FPU state into the owner's save area */
|
||||
if (NpxThread != NULL)
|
||||
{
|
||||
KeGetCurrentKPCR()->PrcbData.NpxThread = NULL;
|
||||
FxSaveArea = (PFX_SAVE_AREA)((char *)NpxThread->InitialStack - sizeof (FX_SAVE_AREA));
|
||||
/* the fnsave might raise a delayed #MF exception */
|
||||
if (FxsrSupport)
|
||||
{
|
||||
asm volatile("fxsave %0" : : "m"(FxSaveArea->U.FxArea));
|
||||
}
|
||||
else
|
||||
{
|
||||
asm volatile("fnsave %0" : : "m"(FxSaveArea->U.FnArea));
|
||||
FpuInitialized = TRUE;
|
||||
}
|
||||
NpxThread->NpxState = NPX_STATE_VALID;
|
||||
}
|
||||
|
||||
/* restore the state of the current thread */
|
||||
ASSERT((CurrentThread->NpxState & NPX_STATE_DIRTY) == 0);
|
||||
FxSaveArea = (PFX_SAVE_AREA)((char *)CurrentThread->InitialStack - sizeof (FX_SAVE_AREA));
|
||||
if (CurrentThread->NpxState & NPX_STATE_VALID)
|
||||
{
|
||||
if (FxsrSupport)
|
||||
{
|
||||
FxSaveArea->U.FxArea.MXCsr &= MxcsrFeatureMask;
|
||||
asm volatile("fxrstor %0" : : "m"(FxSaveArea->U.FxArea));
|
||||
}
|
||||
else
|
||||
{
|
||||
asm volatile("frstor %0" : : "m"(FxSaveArea->U.FnArea));
|
||||
}
|
||||
}
|
||||
else /* NpxState & NPX_STATE_INVALID */
|
||||
{
|
||||
DPRINT("Setting up clean FPU state\n");
|
||||
if (FxsrSupport)
|
||||
{
|
||||
memset(&FxSaveArea->U.FxArea, 0, sizeof(FxSaveArea->U.FxArea));
|
||||
FxSaveArea->U.FxArea.ControlWord = 0x037f;
|
||||
if (XmmSupport)
|
||||
{
|
||||
FxSaveArea->U.FxArea.MXCsr = 0x00001f80 & MxcsrFeatureMask;
|
||||
}
|
||||
asm volatile("fxrstor %0" : : "m"(FxSaveArea->U.FxArea));
|
||||
}
|
||||
else if (!FpuInitialized)
|
||||
{
|
||||
asm volatile("finit");
|
||||
}
|
||||
}
|
||||
KeGetCurrentKPCR()->PrcbData.NpxThread = CurrentThread;
|
||||
}
|
||||
|
||||
CurrentThread->NpxState |= NPX_STATE_DIRTY;
|
||||
KeLowerIrql(oldIrql);
|
||||
DPRINT("Device not present exception handled!\n");
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
else /* ExceptionNr == 16 || ExceptionNr == 19 */
|
||||
{
|
||||
EXCEPTION_RECORD Er;
|
||||
UCHAR DummyContext[sizeof(CONTEXT) + 16];
|
||||
PCONTEXT Context;
|
||||
KPROCESSOR_MODE PreviousMode;
|
||||
PKTHREAD CurrentThread, NpxThread;
|
||||
KIRQL oldIrql;
|
||||
|
||||
ASSERT(ExceptionNr == 16 || ExceptionNr == 19); /* math fault or XMM fault*/
|
||||
|
||||
KeRaiseIrql(DISPATCH_LEVEL, &oldIrql);
|
||||
|
||||
NpxThread = KeGetCurrentKPCR()->PrcbData.NpxThread;
|
||||
CurrentThread = KeGetCurrentThread();
|
||||
if (NpxThread == NULL)
|
||||
{
|
||||
DPRINT1("!!! Math/Xmm fault ignored! (NpxThread == NULL)\n");
|
||||
KeLowerIrql(oldIrql);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
PreviousMode = ((Tf->Cs & 0xffff) == USER_CS) ? (UserMode) : (KernelMode);
|
||||
DPRINT("Math/Xmm fault happened! (PreviousMode = %s)\n",
|
||||
(PreviousMode == UserMode) ? ("UserMode") : ("KernelMode"));
|
||||
|
||||
ASSERT(NpxThread == CurrentThread); /* FIXME: Is not always true I think */
|
||||
|
||||
/* For fxsave we have to align Context->ExtendedRegisters on 16 bytes */
|
||||
Context = (PCONTEXT)DummyContext;
|
||||
Context = (PCONTEXT)((ULONG_PTR)Context + 0x10 - ((ULONG_PTR)Context->ExtendedRegisters & 0x0f));
|
||||
|
||||
/* Get FPU/XMM state */
|
||||
Context->FloatSave.Cr0NpxState = 0;
|
||||
if (FxsrSupport)
|
||||
{
|
||||
PFXSAVE_FORMAT FxSave = (PFXSAVE_FORMAT)Context->ExtendedRegisters;
|
||||
FxSave->MXCsrMask = MxcsrFeatureMask;
|
||||
memset(FxSave->RegisterArea, 0, sizeof(FxSave->RegisterArea) +
|
||||
sizeof(FxSave->Reserved3) + sizeof(FxSave->Reserved4));
|
||||
asm volatile("fxsave %0" : : "m"(*FxSave));
|
||||
KeLowerIrql(oldIrql);
|
||||
KiFxsaveToFnsaveFormat((PFNSAVE_FORMAT)&Context->FloatSave, FxSave);
|
||||
}
|
||||
else
|
||||
{
|
||||
PFNSAVE_FORMAT FnSave = (PFNSAVE_FORMAT)&Context->FloatSave;
|
||||
asm volatile("fnsave %0" : : "m"(*FnSave));
|
||||
KeLowerIrql(oldIrql);
|
||||
memset(Context->FloatSave.RegisterArea, 0, sizeof(Context->FloatSave.RegisterArea));
|
||||
KiFnsaveToFxsaveFormat((PFXSAVE_FORMAT)Context->ExtendedRegisters, FnSave);
|
||||
}
|
||||
|
||||
/* Fill the rest of the context */
|
||||
Context->ContextFlags = CONTEXT_FULL;
|
||||
KeTrapFrameToContext(Tf, Context);
|
||||
Context->ContextFlags |= CONTEXT_FLOATING_POINT | CONTEXT_EXTENDED_REGISTERS;
|
||||
|
||||
/* Determine exception code */
|
||||
if (ExceptionNr == 16)
|
||||
{
|
||||
USHORT FpuStatusWord = Context->FloatSave.StatusWord & 0xffff;
|
||||
DPRINT("FpuStatusWord = 0x%04x\n", FpuStatusWord);
|
||||
|
||||
if (FpuStatusWord & X87_SW_IE)
|
||||
Er.ExceptionCode = EXCEPTION_FLT_INVALID_OPERATION;
|
||||
else if (FpuStatusWord & X87_SW_DE)
|
||||
Er.ExceptionCode = EXCEPTION_FLT_DENORMAL_OPERAND;
|
||||
else if (FpuStatusWord & X87_SW_ZE)
|
||||
Er.ExceptionCode = EXCEPTION_FLT_DIVIDE_BY_ZERO;
|
||||
else if (FpuStatusWord & X87_SW_OE)
|
||||
Er.ExceptionCode = EXCEPTION_FLT_OVERFLOW;
|
||||
else if (FpuStatusWord & X87_SW_UE)
|
||||
Er.ExceptionCode = EXCEPTION_FLT_UNDERFLOW;
|
||||
else if (FpuStatusWord & X87_SW_PE)
|
||||
Er.ExceptionCode = EXCEPTION_FLT_INEXACT_RESULT;
|
||||
else if (FpuStatusWord & X87_SW_SE)
|
||||
Er.ExceptionCode = EXCEPTION_FLT_STACK_CHECK;
|
||||
else
|
||||
ASSERT(0); /* not reached */
|
||||
/* FIXME: is this the right way to get the correct EIP of the faulting instruction? */
|
||||
Er.ExceptionAddress = (PVOID)Context->FloatSave.ErrorOffset;
|
||||
}
|
||||
else /* ExceptionNr == 19 */
|
||||
{
|
||||
/* FIXME: When should we use EXCEPTION_FLT_MULTIPLE_FAULTS? */
|
||||
Er.ExceptionCode = EXCEPTION_FLT_MULTIPLE_TRAPS;
|
||||
Er.ExceptionAddress = (PVOID)Tf->Eip;
|
||||
}
|
||||
|
||||
Er.ExceptionFlags = 0;
|
||||
Er.ExceptionRecord = NULL;
|
||||
Er.NumberParameters = 0;
|
||||
|
||||
/* Dispatch exception */
|
||||
DPRINT("Dispatching exception (ExceptionCode = 0x%08x)\n", Er.ExceptionCode);
|
||||
KiDispatchException(&Er, Context, Tf, PreviousMode, TRUE);
|
||||
|
||||
DPRINT("Math-fault handled!\n");
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
|
|
|
@ -181,8 +181,6 @@ KeApplicationProcessorInit(VOID)
|
|||
Offset = InterlockedIncrement(&PcrsAllocated) - 1;
|
||||
Pcr = (PKPCR)((ULONG_PTR)KPCR_BASE + Offset * PAGE_SIZE);
|
||||
|
||||
KiCheckFPU();
|
||||
|
||||
/*
|
||||
* Initialize the GDT
|
||||
*/
|
||||
|
@ -191,6 +189,9 @@ KeApplicationProcessorInit(VOID)
|
|||
/* Get processor information. */
|
||||
Ki386GetCpuId();
|
||||
|
||||
/* Check FPU/MMX/SSE support. */
|
||||
KiCheckFPU();
|
||||
|
||||
/*
|
||||
* It is now safe to process interrupts
|
||||
*/
|
||||
|
@ -220,14 +221,18 @@ KeInit1(PCHAR CommandLine, PULONG LastKernelAddress)
|
|||
extern USHORT KiBootGdt[];
|
||||
extern KTSS KiBootTss;
|
||||
|
||||
/* Get processor information. */
|
||||
Ki386GetCpuId();
|
||||
|
||||
/* Check FPU/MMX/SSE support. */
|
||||
KiCheckFPU();
|
||||
|
||||
|
||||
KiInitializeGdt (NULL);
|
||||
Ki386BootInitializeTSS();
|
||||
KeInitExceptions ();
|
||||
KeInitInterrupts ();
|
||||
|
||||
/*
|
||||
/*
|
||||
* Initialize the initial PCR region. We can't allocate a page
|
||||
* with MmAllocPage() here because MmInit1() has not yet been
|
||||
* called, so we use a predefined page in low memory
|
||||
|
@ -251,9 +256,6 @@ KeInit1(PCHAR CommandLine, PULONG LastKernelAddress)
|
|||
|
||||
Ki386InitializeLdt();
|
||||
|
||||
/* Get processor information. */
|
||||
Ki386GetCpuId();
|
||||
|
||||
if (KPCR->PrcbData.FeatureBits & X86_FEATURE_PGE)
|
||||
{
|
||||
ULONG Flags;
|
||||
|
@ -348,6 +350,24 @@ KeInit2(VOID)
|
|||
DPRINT1("CPU doesn't run in PAE mode\n");
|
||||
}
|
||||
}
|
||||
if ((Pcr->PrcbData.FeatureBits & (X86_FEATURE_FXSR | X86_FEATURE_MMX | X86_FEATURE_SSE | X86_FEATURE_SSE2)) ||
|
||||
(Ke386CpuidFlags2 & X86_EXT_FEATURE_SSE3))
|
||||
{
|
||||
DPRINT1("CPU supports" "%s%s%s%s%s" ".\n",
|
||||
((Pcr->PrcbData.FeatureBits & X86_FEATURE_FXSR) ? " FXSR" : ""),
|
||||
((Pcr->PrcbData.FeatureBits & X86_FEATURE_MMX) ? " MMX" : ""),
|
||||
((Pcr->PrcbData.FeatureBits & X86_FEATURE_SSE) ? " SSE" : ""),
|
||||
((Pcr->PrcbData.FeatureBits & X86_FEATURE_SSE2) ? " SSE2" : ""),
|
||||
((Ke386CpuidFlags2 & X86_EXT_FEATURE_SSE3) ? " SSE3" : ""));
|
||||
}
|
||||
if (Ke386GetCr4() & X86_CR4_OSFXSR)
|
||||
{
|
||||
DPRINT1("SSE enabled.\n");
|
||||
}
|
||||
if (Ke386GetCr4() & X86_CR4_OSXMMEXCPT)
|
||||
{
|
||||
DPRINT1("Unmasked SIMD exceptions enabled.\n");
|
||||
}
|
||||
if (Pcr->PrcbData.VendorString[0])
|
||||
{
|
||||
DPRINT1("CPU Vendor: %s\n", Pcr->PrcbData.VendorString);
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include <internal/i386/segment.h>
|
||||
#include <internal/ps.h>
|
||||
#include <internal/i386/mm.h>
|
||||
#include <internal/i386/fpu.h>
|
||||
|
||||
#define MULTIBOOT_HEADER_MAGIC (0x1BADB002)
|
||||
|
||||
|
@ -279,7 +280,7 @@ _multiboot_entry:
|
|||
/*
|
||||
* Load the initial kernel stack
|
||||
*/
|
||||
movl $_init_stack_top, %esp
|
||||
movl $(_init_stack_top - SIZEOF_FX_SAVE_AREA), %esp
|
||||
|
||||
/*
|
||||
* Initialize EFLAGS
|
||||
|
|
|
@ -31,13 +31,6 @@
|
|||
#define NDEBUG
|
||||
#include <internal/debug.h>
|
||||
|
||||
/* GLOBALS *******************************************************************/
|
||||
|
||||
#define FLAG_NT (1<<14)
|
||||
#define FLAG_VM (1<<17)
|
||||
#define FLAG_IF (1<<9)
|
||||
#define FLAG_IOPL ((1<<12)+(1<<13))
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
NTSTATUS
|
||||
|
@ -77,10 +70,10 @@ Ki386ValidateUserContext(PCONTEXT Context)
|
|||
{
|
||||
return(STATUS_UNSUCCESSFUL);
|
||||
}
|
||||
if ((Context->EFlags & FLAG_IOPL) != 0 ||
|
||||
(Context->EFlags & FLAG_NT) ||
|
||||
(Context->EFlags & FLAG_VM) ||
|
||||
(!(Context->EFlags & FLAG_IF)))
|
||||
if ((Context->EFlags & X86_EFLAGS_IOPL) != 0 ||
|
||||
(Context->EFlags & X86_EFLAGS_NT) ||
|
||||
(Context->EFlags & X86_EFLAGS_VM) ||
|
||||
(!(Context->EFlags & X86_EFLAGS_IF)))
|
||||
{
|
||||
return(STATUS_UNSUCCESSFUL);
|
||||
}
|
||||
|
@ -93,40 +86,37 @@ Ke386InitThreadWithContext(PKTHREAD Thread, PCONTEXT Context)
|
|||
PULONG KernelStack;
|
||||
ULONG InitSize;
|
||||
PKTRAP_FRAME TrapFrame;
|
||||
PFX_SAVE_AREA FxSaveArea;
|
||||
|
||||
/*
|
||||
* Setup a stack frame for exit from the task switching routine
|
||||
*/
|
||||
|
||||
InitSize = 5 * sizeof(DWORD) + sizeof(DWORD) + 6 * sizeof(DWORD) +
|
||||
sizeof(FLOATING_SAVE_AREA) + sizeof(KTRAP_FRAME);
|
||||
InitSize = 6 * sizeof(DWORD) + sizeof(DWORD) + 6 * sizeof(DWORD) +
|
||||
+ sizeof(KTRAP_FRAME) + sizeof (FX_SAVE_AREA);
|
||||
KernelStack = (PULONG)((char*)Thread->KernelStack - InitSize);
|
||||
|
||||
/* Set up the initial frame for the return from the dispatcher. */
|
||||
KernelStack[0] = 0; /* EDI */
|
||||
KernelStack[1] = 0; /* ESI */
|
||||
KernelStack[2] = 0; /* EBX */
|
||||
KernelStack[3] = 0; /* EBP */
|
||||
KernelStack[4] = (ULONG)&PsBeginThreadWithContextInternal; /* EIP */
|
||||
KernelStack[0] = (ULONG)Thread->InitialStack - sizeof(FX_SAVE_AREA); /* TSS->Esp0 */
|
||||
KernelStack[1] = 0; /* EDI */
|
||||
KernelStack[2] = 0; /* ESI */
|
||||
KernelStack[3] = 0; /* EBX */
|
||||
KernelStack[4] = 0; /* EBP */
|
||||
KernelStack[5] = (ULONG)&PsBeginThreadWithContextInternal; /* EIP */
|
||||
|
||||
/* Save the context flags. */
|
||||
KernelStack[5] = Context->ContextFlags;
|
||||
KernelStack[6] = Context->ContextFlags;
|
||||
|
||||
/* Set up the initial values of the debugging registers. */
|
||||
KernelStack[6] = Context->Dr0;
|
||||
KernelStack[7] = Context->Dr1;
|
||||
KernelStack[8] = Context->Dr2;
|
||||
KernelStack[9] = Context->Dr3;
|
||||
KernelStack[10] = Context->Dr6;
|
||||
KernelStack[11] = Context->Dr7;
|
||||
|
||||
/* Set up the initial floating point state. */
|
||||
memcpy((PVOID)&KernelStack[12], (PVOID)&Context->FloatSave,
|
||||
sizeof(FLOATING_SAVE_AREA));
|
||||
KernelStack[7] = Context->Dr0;
|
||||
KernelStack[8] = Context->Dr1;
|
||||
KernelStack[9] = Context->Dr2;
|
||||
KernelStack[10] = Context->Dr3;
|
||||
KernelStack[11] = Context->Dr6;
|
||||
KernelStack[12] = Context->Dr7;
|
||||
|
||||
/* Set up a trap frame from the context. */
|
||||
TrapFrame = (PKTRAP_FRAME)
|
||||
((char*)KernelStack + 12 * sizeof(DWORD) + sizeof(FLOATING_SAVE_AREA));
|
||||
TrapFrame = (PKTRAP_FRAME)(&KernelStack[13]);
|
||||
TrapFrame->DebugEbp = (PVOID)Context->Ebp;
|
||||
TrapFrame->DebugEip = (PVOID)Context->Eip;
|
||||
TrapFrame->DebugArgMark = 0;
|
||||
|
@ -149,12 +139,24 @@ Ke386InitThreadWithContext(PKTHREAD Thread, PCONTEXT Context)
|
|||
TrapFrame->ErrorCode = 0;
|
||||
TrapFrame->Cs = Context->SegCs;
|
||||
TrapFrame->Eip = Context->Eip;
|
||||
TrapFrame->Eflags = Context->EFlags | FLAG_IF;
|
||||
TrapFrame->Eflags &= ~(FLAG_VM | FLAG_NT | FLAG_IOPL);
|
||||
TrapFrame->Eflags = Context->EFlags | X86_EFLAGS_IF;
|
||||
TrapFrame->Eflags &= ~(X86_EFLAGS_VM | X86_EFLAGS_NT | X86_EFLAGS_IOPL);
|
||||
TrapFrame->Esp = Context->Esp;
|
||||
TrapFrame->Ss = (USHORT)Context->SegSs;
|
||||
/* FIXME: Should check for a v86 mode context here. */
|
||||
|
||||
/* Set up the initial floating point state. */
|
||||
/* FIXME: Do we have to zero the FxSaveArea or is it already? */
|
||||
FxSaveArea = (PFX_SAVE_AREA)((ULONG_PTR)KernelStack + InitSize - sizeof(FX_SAVE_AREA));
|
||||
if (KiContextToFxSaveArea(FxSaveArea, Context))
|
||||
{
|
||||
Thread->NpxState = NPX_STATE_VALID;
|
||||
}
|
||||
else
|
||||
{
|
||||
Thread->NpxState = NPX_STATE_INVALID;
|
||||
}
|
||||
|
||||
/* Save back the new value of the kernel stack. */
|
||||
Thread->KernelStack = (PVOID)KernelStack;
|
||||
|
||||
|
@ -175,21 +177,25 @@ Ke386InitThread(PKTHREAD Thread,
|
|||
* Setup a stack frame for exit from the task switching routine
|
||||
*/
|
||||
|
||||
KernelStack = (PULONG)((char*)Thread->KernelStack - (8*4));
|
||||
KernelStack[0] = 0; /* EDI */
|
||||
KernelStack[1] = 0; /* ESI */
|
||||
KernelStack[2] = 0; /* EBX */
|
||||
KernelStack[3] = 0; /* EBP */
|
||||
KernelStack[4] = (ULONG)&PsBeginThread; /* EIP */
|
||||
KernelStack[5] = 0; /* Return EIP */
|
||||
KernelStack[6] = (ULONG)StartRoutine; /* First argument to PsBeginThread */
|
||||
KernelStack[7] = (ULONG)StartContext; /* Second argument to PsBeginThread */
|
||||
KernelStack = (PULONG)((char*)Thread->KernelStack - (9 * sizeof(DWORD)) - sizeof(FX_SAVE_AREA));
|
||||
KernelStack[0] = (ULONG)Thread->InitialStack - sizeof(FX_SAVE_AREA); /* TSS->Esp0 */
|
||||
KernelStack[1] = 0; /* EDI */
|
||||
KernelStack[2] = 0; /* ESI */
|
||||
KernelStack[3] = 0; /* EBX */
|
||||
KernelStack[4] = 0; /* EBP */
|
||||
KernelStack[5] = (ULONG)&PsBeginThread; /* EIP */
|
||||
KernelStack[6] = 0; /* Return EIP */
|
||||
KernelStack[7] = (ULONG)StartRoutine; /* First argument to PsBeginThread */
|
||||
KernelStack[8] = (ULONG)StartContext; /* Second argument to PsBeginThread */
|
||||
Thread->KernelStack = (VOID*)KernelStack;
|
||||
|
||||
/*
|
||||
* Setup FPU state
|
||||
*/
|
||||
Thread->NpxState = NPX_STATE_INVALID;
|
||||
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* EOF */
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
/* $Id: trap.s,v 1.20 2004/07/01 02:40:23 hyperion Exp $
|
||||
/* $Id: trap.s,v 1.21 2004/11/20 23:46:36 blight Exp $
|
||||
*
|
||||
* PROJECT: ReactOS kernel
|
||||
* FILE: ntoskrnl/ke/i386/trap.s
|
||||
|
@ -353,6 +353,33 @@ _KiTrap16:
|
|||
movl $16, %esi
|
||||
jmp _KiTrapProlog
|
||||
|
||||
.globl _KiTrap17
|
||||
_KiTrap17:
|
||||
pushl $0
|
||||
pushl %ebp
|
||||
pushl %ebx
|
||||
pushl %esi
|
||||
movl $17, %esi
|
||||
jmp _KiTrapProlog
|
||||
|
||||
.globl _KiTrap18
|
||||
_KiTrap18:
|
||||
pushl $0
|
||||
pushl %ebp
|
||||
pushl %ebx
|
||||
pushl %esi
|
||||
movl $18, %esi
|
||||
jmp _KiTrapProlog
|
||||
|
||||
.globl _KiTrap19
|
||||
_KiTrap19:
|
||||
pushl $0
|
||||
pushl %ebp
|
||||
pushl %ebx
|
||||
pushl %esi
|
||||
movl $19, %esi
|
||||
jmp _KiTrapProlog
|
||||
|
||||
.globl _KiTrapUnknown
|
||||
_KiTrapUnknown:
|
||||
pushl $0
|
||||
|
|
|
@ -17,16 +17,18 @@
|
|||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
/*
|
||||
* FILE: ntoskrnl/ke/i386/tskswitch.S
|
||||
* PURPOSE: Microkernel thread support
|
||||
* FILE: ntoskrnl/ke/i386/tskswitch.S
|
||||
* PURPOSE: Microkernel thread support
|
||||
* PROGRAMMER: David Welch (welch@cwcom.net)
|
||||
* UPDATE HISTORY:
|
||||
* Created 09/10/00
|
||||
* Created 09/10/00
|
||||
*/
|
||||
|
||||
/* INCLUDES ******************************************************************/
|
||||
|
||||
#include <internal/i386/segment.h>
|
||||
#include <internal/i386/ke.h>
|
||||
#include <internal/i386/fpu.h>
|
||||
#include <internal/ps.h>
|
||||
#include <ntos/tss.h>
|
||||
#include <internal/ntoskrnl.h>
|
||||
|
@ -34,12 +36,13 @@
|
|||
/* FUNCTIONS ****************************************************************/
|
||||
|
||||
.globl _Ki386ContextSwitch
|
||||
.func Ki386ContextSwitch
|
||||
_Ki386ContextSwitch:
|
||||
/*
|
||||
/*
|
||||
* FUNCTIONS: Switches to another thread's context
|
||||
* ARGUMENTS:
|
||||
* Thread = Thread to switch to
|
||||
* OldThread = Thread to switch from
|
||||
* Thread = Thread to switch to
|
||||
* OldThread = Thread to switch from
|
||||
*/
|
||||
pushl %ebp
|
||||
movl %esp, %ebp
|
||||
|
@ -60,7 +63,7 @@ _Ki386ContextSwitch:
|
|||
* Get the pointer to the new thread.
|
||||
*/
|
||||
movl 8(%ebp), %ebx
|
||||
|
||||
|
||||
/*
|
||||
* Set the base of the TEB selector to the base of the TEB for
|
||||
* this thread.
|
||||
|
@ -89,7 +92,7 @@ _Ki386ContextSwitch:
|
|||
xorl %eax, %eax
|
||||
movl KTHREAD_APCSTATE_PROCESS(%ebx), %edi
|
||||
testw $0xFFFF, KPROCESS_LDT_DESCRIPTOR0(%edi)
|
||||
jz .L4
|
||||
jz 0f
|
||||
|
||||
pushl KPROCESS_LDT_DESCRIPTOR1(%edi)
|
||||
pushl KPROCESS_LDT_DESCRIPTOR0(%edi)
|
||||
|
@ -99,9 +102,15 @@ _Ki386ContextSwitch:
|
|||
|
||||
movl $LDT_SELECTOR, %eax
|
||||
|
||||
.L4:
|
||||
0:
|
||||
lldtw %ax
|
||||
|
||||
movl 12(%ebp), %ebx
|
||||
|
||||
/*
|
||||
* FIXME: Save debugging state.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Load up the iomap offset for this thread in
|
||||
* preparation for setting it below.
|
||||
|
@ -109,25 +118,19 @@ _Ki386ContextSwitch:
|
|||
movl KPROCESS_IOPM_OFFSET(%edi), %eax
|
||||
|
||||
/*
|
||||
* FIXME: Save debugging state.
|
||||
*/
|
||||
|
||||
/*
|
||||
* FIXME: Save floating point state.
|
||||
* Save the stack pointer in this processors TSS
|
||||
*/
|
||||
movl %fs:KPCR_TSS, %esi
|
||||
pushl KTSS_ESP0(%esi)
|
||||
|
||||
/*
|
||||
* Switch stacks
|
||||
*/
|
||||
movl 12(%ebp), %ebx
|
||||
movl %esp, KTHREAD_KERNEL_STACK(%ebx)
|
||||
movl 8(%ebp), %ebx
|
||||
movl KTHREAD_KERNEL_STACK(%ebx), %esp
|
||||
movl KTHREAD_STACK_LIMIT(%ebx), %edi
|
||||
|
||||
/*
|
||||
* Set the stack pointer in this processors TSS
|
||||
*/
|
||||
movl %fs:KPCR_TSS, %esi
|
||||
|
||||
/*
|
||||
|
@ -135,19 +138,28 @@ _Ki386ContextSwitch:
|
|||
*/
|
||||
movw %ax, KTSS_IOMAPBASE(%esi)
|
||||
|
||||
movl KTHREAD_INITIAL_STACK(%ebx), %eax
|
||||
movl %eax, KTSS_ESP0(%esi)
|
||||
|
||||
/*
|
||||
* Change the address space
|
||||
*/
|
||||
movl KTHREAD_APCSTATE_PROCESS(%ebx), %ebx
|
||||
movl KPROCESS_DIRECTORY_TABLE_BASE(%ebx), %eax
|
||||
movl KTHREAD_APCSTATE_PROCESS(%ebx), %eax
|
||||
movl KPROCESS_DIRECTORY_TABLE_BASE(%eax), %eax
|
||||
movl %eax, %cr3
|
||||
|
||||
/*
|
||||
* FIXME: Restore floating point state
|
||||
* Restore the stack pointer in this processors TSS
|
||||
*/
|
||||
popl KTSS_ESP0(%esi)
|
||||
|
||||
/*
|
||||
* Set TS in cr0 to catch FPU code and load the FPU state when needed
|
||||
* We do this only if NewThread != KPCR->NpxThread
|
||||
*/
|
||||
cmpl %ebx, %fs:KPCR_NPX_THREAD
|
||||
je 1f
|
||||
movl %cr0, %eax
|
||||
orl $X86_CR0_TS, %eax
|
||||
movl %eax, %cr0
|
||||
1:
|
||||
|
||||
/*
|
||||
* FIXME: Restore debugging state
|
||||
|
@ -162,9 +174,9 @@ _Ki386ContextSwitch:
|
|||
call _KeReleaseSpinLockFromDpcLevel@4
|
||||
|
||||
cmpl $0, _PiNrThreadsAwaitingReaping
|
||||
je .L3
|
||||
je 4f
|
||||
call _PiWakeupReaperThread@0
|
||||
.L3:
|
||||
4:
|
||||
|
||||
/*
|
||||
* Restore the saved register and exit
|
||||
|
@ -175,3 +187,5 @@ _Ki386ContextSwitch:
|
|||
|
||||
popl %ebp
|
||||
ret
|
||||
.endfunc
|
||||
|
||||
|
|
|
@ -134,7 +134,7 @@ Ki386ApplicationProcessorInitializeTSS(VOID)
|
|||
KeGetCurrentKPCR()->TSS = Tss;
|
||||
|
||||
/* Initialize the boot TSS. */
|
||||
Tss->Esp0 = (ULONG)Ki386InitialStackArray[Id];
|
||||
Tss->Esp0 = (ULONG)Ki386InitialStackArray[Id] + MM_STACK_SIZE; /* FIXME: - sizeof(FX_SAVE_AREA)? */
|
||||
Tss->Ss0 = KERNEL_DS;
|
||||
Tss->IoMapBase = 0xFFFF; /* No i/o bitmap */
|
||||
Tss->IoBitmap[8192] = 0xFF;
|
||||
|
@ -154,9 +154,9 @@ Ki386ApplicationProcessorInitializeTSS(VOID)
|
|||
|
||||
/* Initialize the TSS used for handling double faults. */
|
||||
TrapTss->Eflags = 0;
|
||||
TrapTss->Esp0 = ((ULONG)TrapStack + MM_STACK_SIZE);
|
||||
TrapTss->Esp0 = ((ULONG)TrapStack + MM_STACK_SIZE); /* FIXME: - sizeof(FX_SAVE_AREA)? */
|
||||
TrapTss->Ss0 = KERNEL_DS;
|
||||
TrapTss->Esp = ((ULONG)TrapStack + MM_STACK_SIZE);
|
||||
TrapTss->Esp = ((ULONG)TrapStack + MM_STACK_SIZE); /* FIXME: - sizeof(FX_SAVE_AREA)? */
|
||||
TrapTss->Cs = KERNEL_CS;
|
||||
TrapTss->Eip = (ULONG)KiTrap8;
|
||||
TrapTss->Ss = KERNEL_DS;
|
||||
|
@ -211,7 +211,7 @@ Ki386BootInitializeTSS(VOID)
|
|||
Ki386InitialStackArray[0] = (PVOID)&init_stack;
|
||||
|
||||
/* Initialize the boot TSS. */
|
||||
KiBootTss.Esp0 = (ULONG)&init_stack_top;
|
||||
KiBootTss.Esp0 = (ULONG)&init_stack_top - sizeof(FX_SAVE_AREA);
|
||||
KiBootTss.Ss0 = KERNEL_DS;
|
||||
// KiBootTss.IoMapBase = FIELD_OFFSET(KTSS, IoBitmap);
|
||||
KiBootTss.IoMapBase = 0xFFFF; /* No i/o bitmap */
|
||||
|
@ -232,9 +232,9 @@ Ki386BootInitializeTSS(VOID)
|
|||
|
||||
/* Initialize the TSS used for handling double faults. */
|
||||
KiBootTrapTss.Eflags = 0;
|
||||
KiBootTrapTss.Esp0 = (ULONG)&trap_stack_top;
|
||||
KiBootTrapTss.Esp0 = (ULONG)&trap_stack_top; /* FIXME: - sizeof(FX_SAVE_AREA)? */
|
||||
KiBootTrapTss.Ss0 = KERNEL_DS;
|
||||
KiBootTrapTss.Esp = (ULONG)&trap_stack_top;
|
||||
KiBootTrapTss.Esp = (ULONG)&trap_stack_top; /* FIXME: - sizeof(FX_SAVE_AREA)? */
|
||||
KiBootTrapTss.Cs = KERNEL_CS;
|
||||
KiBootTrapTss.Eip = (ULONG)KiTrap8;
|
||||
KiBootTrapTss.Ss = KERNEL_DS;
|
||||
|
|
|
@ -71,25 +71,19 @@ _Ki386RetToV86Mode:
|
|||
* Since we are going to fiddle with the stack pointer this must be
|
||||
* a critical section for this processor
|
||||
*/
|
||||
|
||||
/*
|
||||
* Save the old initial stack
|
||||
*/
|
||||
movl %fs:KPCR_CURRENT_THREAD, %esi
|
||||
movl KTHREAD_INITIAL_STACK(%esi), %edi
|
||||
pushl %edi
|
||||
|
||||
/*
|
||||
* We also need to set the stack in the kthread structure
|
||||
*/
|
||||
movl %esp, KTHREAD_INITIAL_STACK(%esi)
|
||||
cli
|
||||
|
||||
/*
|
||||
* Save the exception handler stack from the TSS
|
||||
*/
|
||||
movl %fs:KPCR_TSS, %esi
|
||||
pushl KTSS_ESP0(%esi)
|
||||
|
||||
/*
|
||||
* The stack used for handling exceptions from v86 mode in this thread
|
||||
* will be the current stack adjusted so we don't overwrite the
|
||||
* existing stack frames
|
||||
*/
|
||||
movl %fs:KPCR_TSS, %esi
|
||||
movl %esp, KTSS_ESP0(%esi)
|
||||
|
||||
/*
|
||||
|
@ -180,18 +174,10 @@ _KiV86Complete:
|
|||
cli
|
||||
|
||||
/*
|
||||
* Restore the initial stack
|
||||
* Restore the exception handler stack in the TSS
|
||||
*/
|
||||
popl %eax
|
||||
movl %fs:KPCR_TSS, %esi
|
||||
movl %eax, KTSS_ESP0(%esi)
|
||||
|
||||
/*
|
||||
* We also need to set the stack in the kthread structure
|
||||
*/
|
||||
movl %fs:KPCR_CURRENT_THREAD, %esi
|
||||
movl KTHREAD_INITIAL_STACK(%esi), %edi
|
||||
movl %eax, KTHREAD_INITIAL_STACK(%esi)
|
||||
popl KTSS_ESP0(%esi)
|
||||
|
||||
/* Exit the critical section */
|
||||
sti
|
||||
|
@ -207,3 +193,4 @@ _KiV86Complete:
|
|||
movl %ebp, %esp
|
||||
popl %ebp
|
||||
ret
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
/* $Id: main.c,v 1.205 2004/11/13 22:30:18 hbirr Exp $
|
||||
/* $Id: main.c,v 1.206 2004/11/20 23:46:37 blight Exp $
|
||||
*
|
||||
* PROJECT: ReactOS kernel
|
||||
* FILE: ntoskrnl/ke/main.c
|
||||
|
@ -299,6 +299,7 @@ ExpInitializeExecutive(VOID)
|
|||
ASSERT(FIELD_OFFSET(KTHREAD, InitialStack) == KTHREAD_INITIAL_STACK);
|
||||
ASSERT(FIELD_OFFSET(KTHREAD, Teb) == KTHREAD_TEB);
|
||||
ASSERT(FIELD_OFFSET(KTHREAD, KernelStack) == KTHREAD_KERNEL_STACK);
|
||||
ASSERT(FIELD_OFFSET(KTHREAD, NpxState) == KTHREAD_NPX_STATE);
|
||||
ASSERT(FIELD_OFFSET(KTHREAD, ServiceTable) == KTHREAD_SERVICE_TABLE);
|
||||
ASSERT(FIELD_OFFSET(KTHREAD, PreviousMode) == KTHREAD_PREVIOUS_MODE);
|
||||
ASSERT(FIELD_OFFSET(KTHREAD, TrapFrame) == KTHREAD_TRAP_FRAME);
|
||||
|
@ -309,12 +310,20 @@ ExpInitializeExecutive(VOID)
|
|||
ASSERT(FIELD_OFFSET(KPROCESS, IopmOffset) == KPROCESS_IOPM_OFFSET);
|
||||
ASSERT(FIELD_OFFSET(KPROCESS, LdtDescriptor) == KPROCESS_LDT_DESCRIPTOR0);
|
||||
ASSERT(FIELD_OFFSET(KTRAP_FRAME, Reserved9) == KTRAP_FRAME_RESERVED9);
|
||||
ASSERT(FIELD_OFFSET(KV86M_TRAP_FRAME, SavedExceptionStack) == TF_SAVED_EXCEPTION_STACK);
|
||||
ASSERT(FIELD_OFFSET(KV86M_TRAP_FRAME, regs) == TF_REGS);
|
||||
ASSERT(FIELD_OFFSET(KV86M_TRAP_FRAME, orig_ebp) == TF_ORIG_EBP);
|
||||
|
||||
ASSERT(FIELD_OFFSET(KPCR, Tib.ExceptionList) == KPCR_EXCEPTION_LIST);
|
||||
ASSERT(FIELD_OFFSET(KPCR, Self) == KPCR_SELF);
|
||||
ASSERT(FIELD_OFFSET(KPCR, PrcbData) + FIELD_OFFSET(KPRCB, CurrentThread) == KPCR_CURRENT_THREAD);
|
||||
ASSERT(FIELD_OFFSET(KPCR, PrcbData) + FIELD_OFFSET(KPRCB, NpxThread) == KPCR_NPX_THREAD);
|
||||
|
||||
ASSERT(FIELD_OFFSET(KTSS, Esp0) == KTSS_ESP0);
|
||||
ASSERT(FIELD_OFFSET(KTSS, Eflags) == KTSS_EFLAGS);
|
||||
ASSERT(FIELD_OFFSET(KTSS, IoMapBase) == KTSS_IOMAPBASE);
|
||||
|
||||
ASSERT(sizeof(FX_SAVE_AREA) == SIZEOF_FX_SAVE_AREA);
|
||||
|
||||
LdrInit1();
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
/* $Id: debug.c,v 1.14 2004/10/24 20:37:27 weiden Exp $
|
||||
/* $Id: debug.c,v 1.15 2004/11/20 23:46:37 blight Exp $
|
||||
*
|
||||
* PROJECT: ReactOS kernel
|
||||
* FILE: ntoskrnl/ps/debug.c
|
||||
|
@ -77,6 +77,9 @@ KeContextToTrapFrame(PCONTEXT Context,
|
|||
{
|
||||
/*
|
||||
* Not handled
|
||||
*
|
||||
* This should be handled separately I think.
|
||||
* - blight
|
||||
*/
|
||||
}
|
||||
if ((Context->ContextFlags & CONTEXT_DEBUG_REGISTERS) == CONTEXT_DEBUG_REGISTERS)
|
||||
|
@ -129,19 +132,33 @@ KeTrapFrameToContext(PKTRAP_FRAME TrapFrame,
|
|||
/*
|
||||
* FIXME: Implement this case
|
||||
*/
|
||||
Context->ContextFlags &= (~CONTEXT_DEBUG_REGISTERS) | CONTEXT_i386;
|
||||
}
|
||||
if ((Context->ContextFlags & CONTEXT_FLOATING_POINT) == CONTEXT_FLOATING_POINT)
|
||||
{
|
||||
/*
|
||||
* FIXME: Implement this case
|
||||
*
|
||||
* I think this should only be filled for FPU exceptions, otherwise I
|
||||
* would not know where to get it from as it can be the current state
|
||||
* of the FPU or already saved in the thread's FPU save area.
|
||||
* -blight
|
||||
*/
|
||||
Context->ContextFlags &= (~CONTEXT_FLOATING_POINT) | CONTEXT_i386;
|
||||
}
|
||||
#if 0
|
||||
if ((Context->ContextFlags & CONTEXT_EXTENDED_REGISTERS) == CONTEXT_EXTENDED_REGISTERS)
|
||||
{
|
||||
/*
|
||||
* FIXME: Investigate this
|
||||
*
|
||||
* This is the XMM state (first 512 bytes of FXSAVE_FORMAT/FX_SAVE_AREA)
|
||||
* This should only be filled in case of a SIMD exception I think, so
|
||||
* this is not the right place (like for FPU the state could already be
|
||||
* saved in the thread's FX_SAVE_AREA or still be in the CPU)
|
||||
* -blight
|
||||
*/
|
||||
Context->ContextFlags &= ~CONTEXT_EXTENDED_REGISTERS;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id: continue.c,v 1.5 2004/08/15 16:39:11 chorns Exp $
|
||||
/* $Id: continue.c,v 1.6 2004/11/20 23:46:37 blight Exp $
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
|
@ -32,6 +32,8 @@ NtContinue (
|
|||
{
|
||||
PKTRAP_FRAME TrapFrame = KeGetCurrentThread()->TrapFrame;
|
||||
PKTRAP_FRAME PrevTrapFrame = (PKTRAP_FRAME)TrapFrame->Edx;
|
||||
PFX_SAVE_AREA FxSaveArea;
|
||||
KIRQL oldIrql;
|
||||
|
||||
DPRINT("NtContinue: Context: Eip=0x%x, Esp=0x%x\n", Context->Eip, Context->Esp );
|
||||
PULONG Frame = 0;
|
||||
|
@ -54,12 +56,32 @@ NtContinue (
|
|||
}
|
||||
|
||||
/*
|
||||
* Copy the supplied context over the register information that was saved
|
||||
* on entry to kernel mode, it will then be restored on exit
|
||||
* FIXME: Validate the context
|
||||
*/
|
||||
* Copy the supplied context over the register information that was saved
|
||||
* on entry to kernel mode, it will then be restored on exit
|
||||
* FIXME: Validate the context
|
||||
*/
|
||||
KeContextToTrapFrame ( Context, TrapFrame );
|
||||
|
||||
/* Put the floating point context into the thread's FX_SAVE_AREA
|
||||
* and make sure it is reloaded when needed.
|
||||
*/
|
||||
FxSaveArea = (PFX_SAVE_AREA)((ULONG_PTR)KeGetCurrentThread()->InitialStack - sizeof(FX_SAVE_AREA));
|
||||
if (KiContextToFxSaveArea(FxSaveArea, Context))
|
||||
{
|
||||
KeGetCurrentThread()->NpxState = NPX_STATE_VALID;
|
||||
KeRaiseIrql(DISPATCH_LEVEL, &oldIrql);
|
||||
if (KeGetCurrentKPCR()->PrcbData.NpxThread == KeGetCurrentThread())
|
||||
{
|
||||
KeGetCurrentKPCR()->PrcbData.NpxThread = NULL;
|
||||
Ke386SetCr0(Ke386GetCr0() | X86_CR0_TS);
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSERT((Ke386GetCr0() & X86_CR0_TS) == X86_CR0_TS);
|
||||
}
|
||||
KeLowerIrql(oldIrql);
|
||||
}
|
||||
|
||||
KeRosTrapReturn ( TrapFrame, PrevTrapFrame );
|
||||
|
||||
return STATUS_SUCCESS; /* this doesn't actually happen b/c KeRosTrapReturn() won't return */
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id: kill.c,v 1.84 2004/11/20 16:46:05 weiden Exp $
|
||||
/* $Id: kill.c,v 1.85 2004/11/20 23:46:37 blight Exp $
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
|
@ -136,10 +136,17 @@ PsTerminateCurrentThread(NTSTATUS ExitStatus)
|
|||
CurrentThread->ExitStatus = ExitStatus;
|
||||
KeQuerySystemTime((PLARGE_INTEGER)&CurrentThread->ExitTime);
|
||||
KeCancelTimer(&CurrentThread->Tcb.Timer);
|
||||
|
||||
|
||||
/* If the ProcessoR Control Block's NpxThread points to the current thread
|
||||
* unset it.
|
||||
*/
|
||||
InterlockedCompareExchange((LONG *)&KeGetCurrentKPCR()->PrcbData.NpxThread,
|
||||
(LONG)NULL, (LONG)ETHREAD_TO_KTHREAD(CurrentThread));
|
||||
|
||||
KeReleaseSpinLock(&PiThreadLock, oldIrql);
|
||||
|
||||
PsLockProcess(CurrentProcess, FALSE);
|
||||
|
||||
/* Remove the thread from the thread list of its process */
|
||||
RemoveEntryList(&CurrentThread->ThreadListEntry);
|
||||
Last = IsListEmpty(&CurrentProcess->ThreadListHead);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id: w32call.c,v 1.17 2004/10/30 23:48:57 navaraf Exp $
|
||||
/* $Id: w32call.c,v 1.18 2004/11/20 23:46:37 blight Exp $
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
|
@ -44,6 +44,7 @@ typedef struct _NTW32CALL_SAVED_STATE
|
|||
PNTSTATUS CallbackStatus;
|
||||
PKTRAP_FRAME SavedTrapFrame;
|
||||
PVOID SavedCallbackStack;
|
||||
PVOID SavedExceptionStack;
|
||||
} NTW32CALL_SAVED_STATE, *PNTW32CALL_SAVED_STATE;
|
||||
|
||||
typedef struct
|
||||
|
@ -81,6 +82,7 @@ NtCallbackReturn (PVOID Result,
|
|||
PNTW32CALL_SAVED_STATE State;
|
||||
PKTRAP_FRAME SavedTrapFrame;
|
||||
PVOID SavedCallbackStack;
|
||||
PVOID SavedExceptionStack;
|
||||
|
||||
Thread = PsGetCurrentThread();
|
||||
if (Thread->Tcb.CallbackStack == NULL)
|
||||
|
@ -102,7 +104,8 @@ NtCallbackReturn (PVOID Result,
|
|||
StackLimit = State->SavedStackLimit;
|
||||
SavedTrapFrame = State->SavedTrapFrame;
|
||||
SavedCallbackStack = State->SavedCallbackStack;
|
||||
|
||||
SavedExceptionStack = State->SavedExceptionStack;
|
||||
|
||||
/*
|
||||
* Copy the callback status and the callback result to NtW32Call
|
||||
*/
|
||||
|
@ -124,12 +127,20 @@ NtCallbackReturn (PVOID Result,
|
|||
* Restore the old stack.
|
||||
*/
|
||||
KeRaiseIrql(HIGH_LEVEL, &oldIrql);
|
||||
if ((Thread->Tcb.NpxState & NPX_STATE_VALID) &&
|
||||
ETHREAD_TO_KTHREAD(Thread) != KeGetCurrentKPCR()->PrcbData.NpxThread)
|
||||
{
|
||||
memcpy((char*)InitialStack - sizeof(FX_SAVE_AREA),
|
||||
(char*)Thread->Tcb.InitialStack - sizeof(FX_SAVE_AREA),
|
||||
sizeof(FX_SAVE_AREA));
|
||||
}
|
||||
Thread->Tcb.InitialStack = InitialStack;
|
||||
Thread->Tcb.StackBase = StackBase;
|
||||
Thread->Tcb.StackLimit = StackLimit;
|
||||
Thread->Tcb.TrapFrame = SavedTrapFrame;
|
||||
Thread->Tcb.CallbackStack = SavedCallbackStack;
|
||||
KeGetCurrentKPCR()->TSS->Esp0 = (ULONG)Thread->Tcb.InitialStack;
|
||||
KeGetCurrentKPCR()->TSS->Esp0 = (ULONG)SavedExceptionStack;
|
||||
Ke386SetCr0(Ke386GetCr0() | X86_CR0_TS); /* set TS */
|
||||
KeStackSwitchAndRet((PVOID)(OldStack + 1));
|
||||
|
||||
/* Should never return. */
|
||||
|
@ -258,7 +269,7 @@ NtW32Call (IN ULONG RoutineIndex,
|
|||
Thread = PsGetCurrentThread();
|
||||
|
||||
/* Set up the new kernel and user environment. */
|
||||
StackSize = (ULONG_PTR)(Thread->Tcb.StackBase - Thread->Tcb.StackLimit);
|
||||
StackSize = (ULONG_PTR)Thread->Tcb.StackBase - Thread->Tcb.StackLimit;
|
||||
KeAcquireSpinLock(&CallbackStackListLock, &oldIrql);
|
||||
if (IsListEmpty(&CallbackStackListHead))
|
||||
{
|
||||
|
@ -274,18 +285,18 @@ NtW32Call (IN ULONG RoutineIndex,
|
|||
|
||||
StackEntry = RemoveHeadList(&CallbackStackListHead);
|
||||
KeReleaseSpinLock(&CallbackStackListLock, oldIrql);
|
||||
AssignedStack = CONTAINING_RECORD(StackEntry, NTW32CALL_CALLBACK_STACK,
|
||||
AssignedStack = CONTAINING_RECORD(StackEntry, NTW32CALL_CALLBACK_STACK,
|
||||
ListEntry);
|
||||
NewStack = AssignedStack->BaseAddress;
|
||||
|
||||
|
||||
MmUpdatePageDir(PsGetCurrentProcess(), NewStack, StackSize);
|
||||
|
||||
}
|
||||
/* FIXME: Need to check whether we were interrupted from v86 mode. */
|
||||
memcpy((char*)NewStack + StackSize - sizeof(KTRAP_FRAME), Thread->Tcb.TrapFrame,
|
||||
sizeof(KTRAP_FRAME) - (4 * sizeof(DWORD)));
|
||||
NewFrame = (PKTRAP_FRAME)((char*)NewStack + StackSize - sizeof(KTRAP_FRAME));
|
||||
NewFrame->Esp -= (ArgumentLength + (4 * sizeof(ULONG)));
|
||||
memcpy((char*)NewStack + StackSize - sizeof(KTRAP_FRAME) - sizeof(FX_SAVE_AREA),
|
||||
Thread->Tcb.TrapFrame, sizeof(KTRAP_FRAME) - (4 * sizeof(DWORD)));
|
||||
NewFrame = (PKTRAP_FRAME)((char*)NewStack + StackSize - sizeof(KTRAP_FRAME) - sizeof(FX_SAVE_AREA));
|
||||
NewFrame->Esp -= (ArgumentLength + (4 * sizeof(ULONG)));
|
||||
NewFrame->Eip = (ULONG)LdrpGetSystemDllCallbackDispatcher();
|
||||
UserEsp = (PULONG)NewFrame->Esp;
|
||||
UserEsp[0] = 0; /* Return address. */
|
||||
|
@ -304,10 +315,18 @@ NtW32Call (IN ULONG RoutineIndex,
|
|||
SavedState.CallbackStatus = &CallbackStatus;
|
||||
SavedState.SavedTrapFrame = Thread->Tcb.TrapFrame;
|
||||
SavedState.SavedCallbackStack = Thread->Tcb.CallbackStack;
|
||||
SavedState.SavedExceptionStack = (PVOID)KeGetCurrentKPCR()->TSS->Esp0;
|
||||
if ((Thread->Tcb.NpxState & NPX_STATE_VALID) &&
|
||||
ETHREAD_TO_KTHREAD(Thread) != KeGetCurrentKPCR()->PrcbData.NpxThread)
|
||||
{
|
||||
memcpy((char*)NewStack + StackSize - sizeof(FX_SAVE_AREA),
|
||||
(char*)SavedState.SavedInitialStack - sizeof(FX_SAVE_AREA),
|
||||
sizeof(FX_SAVE_AREA));
|
||||
}
|
||||
Thread->Tcb.InitialStack = Thread->Tcb.StackBase = (char*)NewStack + StackSize;
|
||||
Thread->Tcb.StackLimit = (ULONG_PTR)NewStack;
|
||||
Thread->Tcb.KernelStack = (char*)NewStack + StackSize - sizeof(KTRAP_FRAME);
|
||||
KeGetCurrentKPCR()->TSS->Esp0 = (ULONG)Thread->Tcb.InitialStack;
|
||||
Thread->Tcb.StackLimit = (ULONG)NewStack;
|
||||
Thread->Tcb.KernelStack = (char*)NewStack + StackSize - sizeof(KTRAP_FRAME) - sizeof(FX_SAVE_AREA);
|
||||
KeGetCurrentKPCR()->TSS->Esp0 = (ULONG)Thread->Tcb.InitialStack - sizeof(FX_SAVE_AREA);
|
||||
KePushAndStackSwitchAndSysRet((ULONG)&SavedState, Thread->Tcb.KernelStack);
|
||||
|
||||
/*
|
||||
|
|
Loading…
Reference in a new issue