Some work-in-progress improvements and rethought of system-level code...notable improvemnts till now are: -The KTHREAD alterted flag is now properly set to FALSE during APC delivery during traps, -More support for PKEXCEPTION_FRAME has been added for future PPC/IA64/etc compatibility -Context to/from TrapFrame functions have been greatly fixed to allow for edited frames, special cases, exceptions and also have the necessary support for supporting sanitation based on PreviousMode - KDBG now shows the proper CS/SS at all times, previous hack was removed. - Systemcall code was optimized a bit and the trap code was made a lot more generic so that in can be made into macros (it currently isn't, for debugging purposes). - V86 Mode trap frame bias has now been added to make trap code a lot more generic and shareable in the future. -More support and fixes for future Debugging capabilities have been added. - Random other scalability and stability code. This is still being worked on, syscall.S looks nasty for now (visually)

svn path=/trunk/; revision=17838
This commit is contained in:
Alex Ionescu 2005-09-13 19:33:49 +00:00
parent 3b0cfca870
commit 7a5244c46d
18 changed files with 1124 additions and 374 deletions

View file

@ -256,13 +256,13 @@ LdrpInit(PCONTEXT Context,
SYSTEM_BASIC_INFORMATION SystemInformation;
NTSTATUS Status;
DPRINT("LdrpInit()\n");
DPRINT1("LdrpInit()\n");
if (NtCurrentPeb()->Ldr == NULL || NtCurrentPeb()->Ldr->Initialized == FALSE)
{
Peb = (PPEB)(PEB_BASE);
DPRINT("Peb %x\n", Peb);
DPRINT1("Peb %x\n", Peb);
ImageBase = Peb->ImageBaseAddress;
DPRINT("ImageBase %x\n", ImageBase);
DPRINT1("ImageBase %x\n", ImageBase);
if (ImageBase <= (PVOID)0x1000)
{
DPRINT("ImageBase is null\n");
@ -271,7 +271,7 @@ LdrpInit(PCONTEXT Context,
/* If MZ header exists */
PEDosHeader = (PIMAGE_DOS_HEADER) ImageBase;
DPRINT("PEDosHeader %x\n", PEDosHeader);
DPRINT1("PEDosHeader %x\n", PEDosHeader);
if (PEDosHeader->e_magic != IMAGE_DOS_SIGNATURE ||
PEDosHeader->e_lfanew == 0L ||
@ -294,10 +294,12 @@ LdrpInit(PCONTEXT Context,
NTHeaders = (PIMAGE_NT_HEADERS)((ULONG_PTR)ImageBase + PEDosHeader->e_lfanew);
/* Get number of processors */
DPRINT1("Here\n");
Status = ZwQuerySystemInformation(SystemBasicInformation,
&SystemInformation,
sizeof(SYSTEM_BASIC_INFORMATION),
NULL);
DPRINT1("Here2\n");
if (!NT_SUCCESS(Status))
{
ZwTerminateProcess(NtCurrentProcess(), Status);

View file

@ -165,7 +165,7 @@ RtlDispatchException(IN PEXCEPTION_RECORD ExceptionRecord,
}
/* Unhandled, return false */
DPRINT1("FALSE:(\n");
DPRINT1("FALSE\n");
return FALSE;
}

View file

@ -241,7 +241,6 @@ ExecuteRuntimeAsserts(VOID)
ASSERT(FIELD_OFFSET(KPROCESS, DirectoryTableBase) == KPROCESS_DIRECTORY_TABLE_BASE);
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);

View file

@ -40,11 +40,15 @@
#define X86_EXT_FEATURE_SSE3 0x00000001 /* SSE3 extension present */
#define X86_EXT_FEATURE_3DNOW 0x40000000 /* 3DNOW! extension present */
#define DR7_ACTIVE 0x00000055 /* If any of these bits are set, a Dr is active */
/* Possible values for KTHREAD's NpxState */
#define NPX_STATE_INVALID 0x01
#define NPX_STATE_VALID 0x02
#define NPX_STATE_DIRTY 0x04
#define FRAME_EDITED 0xFFF8
#ifndef __ASM__
typedef struct _KIRQ_TRAPFRAME

View file

@ -287,7 +287,10 @@ VOID inline FASTCALL KiSatisifyMultipleObjectWaits(PKWAIT_BLOCK WaitBlock);
VOID FASTCALL KiWaitTest(PDISPATCHER_HEADER Object, KPRIORITY Increment);
PULONG KeGetStackTopThread(struct _ETHREAD* Thread);
BOOLEAN STDCALL KeContextToTrapFrame(PCONTEXT Context, PKEXCEPTION_FRAME ExeptionFrame, PKTRAP_FRAME TrapFrame);
BOOLEAN STDCALL KeContextToTrapFrame(PCONTEXT Context,
PKEXCEPTION_FRAME ExeptionFrame,
PKTRAP_FRAME TrapFrame,
KPROCESSOR_MODE PreviousMode);
VOID STDCALL KiDeliverApc(KPROCESSOR_MODE PreviousMode,
PVOID Reserved,
PKTRAP_FRAME TrapFrame);
@ -368,8 +371,11 @@ KiDispatchException(PEXCEPTION_RECORD ExceptionRecord,
PKTRAP_FRAME Tf,
KPROCESSOR_MODE PreviousMode,
BOOLEAN SearchFrames);
VOID KeTrapFrameToContext(PKTRAP_FRAME TrapFrame,
PCONTEXT Context);
VOID
NTAPI
KeTrapFrameToContext(IN PKTRAP_FRAME TrapFrame,
IN PKEXCEPTION_FRAME ExceptionFrame,
IN OUT PCONTEXT Context);
VOID
KeApplicationProcessorInit(VOID);
VOID

View file

@ -1321,7 +1321,7 @@ KdpGdbEnterDebuggerException(PEXCEPTION_RECORD ExceptionRecord,
#error Unknown compiler for inline assembler
#endif
KeContextToTrapFrame(Context, NULL, TrapFrame);
KeContextToTrapFrame(Context, NULL, TrapFrame, KernelMode);
return ((SigVal == 5) ? (kdContinue) : (kdHandleException));
break;
}
@ -1430,11 +1430,11 @@ GspBreakIn(PKINTERRUPT Interrupt,
TrapFrame = PsGetCurrentThread()->Tcb.TrapFrame;
KeTrapFrameToContext (TrapFrame, &Context);
KeTrapFrameToContext (TrapFrame, NULL, &Context);
KdpGdbEnterDebuggerException (NULL, &Context, TrapFrame);
KeContextToTrapFrame (&Context, NULL, TrapFrame);
KeContextToTrapFrame (&Context, NULL, TrapFrame, KernelMode);
KeLowerIrql (OldIrql);

View file

@ -15,10 +15,6 @@
/* TYPES *********************************************************************/
/* FIXME: NDK headers */
#define TempEsp TempEip
#define TempSegSs TempCs
/* DEFINES *******************************************************************/
#define KDB_STACK_SIZE (4096*3)
@ -108,6 +104,24 @@ STATIC CONST PCHAR ExceptionNrToString[] =
"SIMD Fault"
};
ULONG
NTAPI
KiSsFromTrapFrame(IN PKTRAP_FRAME TrapFrame);
ULONG
NTAPI
KiEspFromTrapFrame(IN PKTRAP_FRAME TrapFrame);
VOID
NTAPI
KiSsToTrapFrame(IN PKTRAP_FRAME TrapFrame,
IN ULONG Ss);
VOID
NTAPI
KiEspToTrapFrame(IN PKTRAP_FRAME TrapFrame,
IN ULONG Esp);
/* FUNCTIONS *****************************************************************/
STATIC VOID
@ -124,22 +138,11 @@ KdbpTrapFrameToKdbTrapFrame(PKTRAP_FRAME TrapFrame, PKDB_KTRAP_FRAME KdbTrapFram
"movl %%cr4, %3" "\n\t"
: "=r"(KdbTrapFrame->Cr0), "=r"(KdbTrapFrame->Cr2),
"=r"(KdbTrapFrame->Cr3), "=r"(KdbTrapFrame->Cr4));
if (TrapFrame->PreviousMode == KernelMode)
{
/* If the trapframe is a kmode one use the temp ss:esp */
KdbTrapFrame->Tf.Esp = (ULONG)TrapFrame->TempEsp;
KdbTrapFrame->Tf.Ss = (USHORT)((ULONG)TrapFrame->TempSegSs & 0xFFFF);
}
else
{
/* Otherwise use ss:esp pushed by the CPU */
/* FIXME: maybe change all trapframes to always put ss:esp into tempss:tempesp so we
* can handle umode and kmode the same way */
KdbTrapFrame->Tf.Esp = TrapFrame->Esp;
KdbTrapFrame->Tf.Ss = TrapFrame->Ss;
}
KdbTrapFrame->Tf.Esp = KiEspFromTrapFrame(TrapFrame);
KdbTrapFrame->Tf.Ss = (USHORT)(KiSsFromTrapFrame(TrapFrame) & 0xFFFF);
/* FIXME: copy v86 registers if TrapFrame is a V86 trapframe */
}
@ -151,20 +154,8 @@ KdbpKdbTrapFrameToTrapFrame(PKDB_KTRAP_FRAME KdbTrapFrame, PKTRAP_FRAME TrapFram
/* FIXME: write cr0, cr2, cr3 and cr4 (not needed atm) */
if (TrapFrame->PreviousMode == KernelMode)
{
/* If the trapframe is a kmode one write to the temp ss:esp */
TrapFrame->TempEsp = (PVOID)KdbTrapFrame->Tf.Esp;
TrapFrame->TempSegSs = (PVOID)(((ULONG)TrapFrame->TempSegSs & ~0xffff) | KdbTrapFrame->Tf.Ss);
}
else
{
/* Otherwise write to ss:esp pushed by the CPU */
/* FIXME: maybe change all trap-epilogs to always put temp ss:esp into ss:esp so we
* can handle umode and kmode the same way */
TrapFrame->Esp = KdbTrapFrame->Tf.Esp;
TrapFrame->Ss = KdbTrapFrame->Tf.Ss;
}
KiSsToTrapFrame(TrapFrame, KdbTrapFrame->Tf.Ss);
KiEspToTrapFrame(TrapFrame, KdbTrapFrame->Tf.Esp);
/* FIXME: copy v86 registers if TrapFrame is a V86 trapframe */
}

View file

@ -35,10 +35,6 @@
/* DEFINES *******************************************************************/
/* FIXME: NDK headers */
#define TempEsp TempEip
#define TempSegSs TempCs
#define KEY_BS 8
#define KEY_ESC 27
#define KEY_DEL 127

View file

@ -812,7 +812,7 @@ KiInitializeUserApc(IN PKEXCEPTION_FRAME ExceptionFrame,
/* Save the full context */
Context.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS;
KeTrapFrameToContext(TrapFrame, &Context);
KeTrapFrameToContext(TrapFrame, ExceptionFrame, &Context);
/* Protect with SEH */
_SEH_TRY

View file

@ -28,7 +28,7 @@ KiContinuePreviousModeUser(IN PCONTEXT Context,
Context = &LocalContext;
/* Convert the context into Exception/Trap Frames */
KeContextToTrapFrame(&LocalContext, ExceptionFrame, TrapFrame);
KeContextToTrapFrame(&LocalContext, ExceptionFrame, TrapFrame, UserMode);
}
NTSTATUS
@ -62,7 +62,7 @@ KiContinue(IN PCONTEXT Context,
else
{
/* Convert the context into Exception/Trap Frames */
KeContextToTrapFrame(Context, ExceptionFrame, TrapFrame);
KeContextToTrapFrame(Context, ExceptionFrame, TrapFrame, KernelMode);
}
}
_SEH_HANDLE
@ -142,7 +142,7 @@ KiRaiseException(PEXCEPTION_RECORD ExceptionRecord,
if (NT_SUCCESS(Status))
{
/* Convert the context record */
KeContextToTrapFrame(Context, ExceptionFrame, TrapFrame);
KeContextToTrapFrame(Context, ExceptionFrame, TrapFrame, PreviousMode);
/* Dispatch the exception */
KiDispatchException(ExceptionRecord,

View file

@ -114,7 +114,7 @@ BadThread:
.globl @KiSwapContextInternal@0
@KiSwapContextInternal@0:
#ifdef KDBG
jmp SaveTrapFrameForKDB
//jmp SaveTrapFrameForKDB
SaveTrapFrameForKDB_Return:
#endif
@ -130,12 +130,14 @@ SaveTrapFrameForKDB_Return:
/* Switching, disable interrupts now */
cli
/* Save the initial stack in EAX */
mov eax, [edi+KTHREAD_INITIAL_STACK]
#ifdef CONFIG_SMP
/* Save FPU state if the thread has used it. */
mov dword ptr [ebx+KPCR_NPX_THREAD], 0
test byte ptr [edi+KTHREAD_NPX_STATE], NPX_STATE_DIRTY
jz 3f
mov eax, [edi+KTHREAD_INITIAL_STACK]
cmp dword ptr _FxsrSupport, 0
je 1f
fxsave [eax-SIZEOF_FX_SAVE_AREA]
@ -149,8 +151,18 @@ SaveTrapFrameForKDB_Return:
/* Save the stack pointer in this processors TSS */
mov ebp, [ebx+KPCR_TSS]
/* Check if this isn't V86 Mode, so we can bias the Esp0 */
test dword ptr [eax - KTRAP_FRAME_SIZE + KTRAP_FRAME_EFLAGS], X86_EFLAGS_VM
jnz NoAdjust
/* Bias esp */
//sub dword ptr ss:[ebp+KTSS_ESP0], KTRAP_FRAME_V86_GS - KTRAP_FRAME_SS
NoAdjust:
/* Push ESP0 Value */
push ss:[ebp+KTSS_ESP0]
/* Check if address space switch is needed */
mov eax, [esi+KTHREAD_APCSTATE_PROCESS]
cmp eax, [edi+KTHREAD_APCSTATE_PROCESS]

View file

@ -17,14 +17,18 @@
/*
* FIXMES:
* - Put back VEH.
* - Clean up file.
* - Add more exception frame support for non-i386 compatibility.
* - Sanitize some context fields.
* - Add PSEH handler when an exception occurs in an exception (KiCopyExceptionRecord).
* - Implement official stack trace functions (exported) and remove stuff here.
* - Forward exceptions to user-mode debugger.
* - Wrap Ki NTDLL callbacks in SEH.
*/
VOID
NTAPI
Ki386AdjustEsp0(IN PKTRAP_FRAME TrapFrame);
/* GLOBALS *****************************************************************/
#define FLAG_IF (1<<9)
@ -485,14 +489,14 @@ KiTrapHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr)
ASSERT(ExceptionNr != 14);
/* Store the exception number in an unused field in the trap frame. */
Tf->DebugArgMark = (PVOID)ExceptionNr;
Tf->DebugArgMark = ExceptionNr;
/* Use the address of the trap frame as approximation to the ring0 esp */
Esp0 = (ULONG)&Tf->Eip;
/* Get CR2 */
cr2 = Ke386GetCr2();
Tf->DebugPointer = (PVOID)cr2;
Tf->DebugPointer = cr2;
/*
* If this was a V86 mode exception then handle it specially
@ -566,21 +570,172 @@ KiTrapHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr)
}
}
BOOLEAN
STDCALL
KeContextToTrapFrame(PCONTEXT Context,
PKEXCEPTION_FRAME ExceptionFrame,
PKTRAP_FRAME TrapFrame)
ULONG
NTAPI
KiEspFromTrapFrame(IN PKTRAP_FRAME TrapFrame)
{
/* Check if this is user-mode or V86 */
if ((TrapFrame->Cs & 1) || (TrapFrame->Eflags & X86_EFLAGS_VM))
{
/* Return it directly */
return TrapFrame->Esp;
}
else
{
/* Edited frame */
if (!(TrapFrame->Cs & FRAME_EDITED))
{
/* Return edited value */
return TrapFrame->TempEsp;
}
else
{
/* Virgin frame, calculate */
return (ULONG)&TrapFrame->Esp;
}
}
}
VOID
NTAPI
KiEspToTrapFrame(IN PKTRAP_FRAME TrapFrame,
IN ULONG Esp)
{
ULONG Previous = KiEspFromTrapFrame(TrapFrame);
/* Check if this is user-mode or V86 */
if ((TrapFrame->Cs & 1) || (TrapFrame->Eflags & X86_EFLAGS_VM))
{
/* Write it directly */
TrapFrame->Esp = Esp;
}
else
{
/* Don't allow ESP to be lowered, this is illegal */
if (Esp < Previous)
{
//KeBugCheck(SET_OF_INVALID_CONTEXT);
}
/* Create an edit frame, check if it was alrady */
if (!(TrapFrame->Cs & FRAME_EDITED))
{
/* Update the value */
TrapFrame->TempEsp = Esp;
}
else
{
/* Check if ESP changed */
if (Previous != Esp)
{
/* Save CS */
TrapFrame->TempCs = TrapFrame->Cs;
TrapFrame->Cs &= ~FRAME_EDITED;
/* Save ESP */
TrapFrame->TempEsp = Esp;
}
}
}
}
ULONG
NTAPI
KiSsFromTrapFrame(IN PKTRAP_FRAME TrapFrame)
{
/* If this was V86 Mode */
if (TrapFrame->Eflags & X86_EFLAGS_VM)
{
/* Just return it */
return TrapFrame->Ss;
}
else if (TrapFrame->Cs & 1)
{
/* Usermode, return the User SS */
return TrapFrame->Ss | 3;
}
else
{
/* Kernel mode */
return KERNEL_DS;
}
}
VOID
NTAPI
KiSsToTrapFrame(IN PKTRAP_FRAME TrapFrame,
IN ULONG Ss)
{
/* Remove the high-bits */
Ss &= 0xFFFF;
/* If this was V86 Mode */
if (TrapFrame->Eflags & X86_EFLAGS_VM)
{
/* Just write it */
TrapFrame->Ss = Ss;
}
else if (TrapFrame->Cs & 1)
{
/* Usermode, save the User SS */
TrapFrame->Ss = Ss | 3;
}
}
BOOLEAN
NTAPI
KeContextToTrapFrame(IN PCONTEXT Context,
IN OUT PKEXCEPTION_FRAME ExceptionFrame,
IN OUT PKTRAP_FRAME TrapFrame,
IN KPROCESSOR_MODE PreviousMode)
{
BOOLEAN V86Switch = FALSE;
/* Start with the basic Registers */
if ((Context->ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL)
{
TrapFrame->Esp = Context->Esp;
TrapFrame->Ss = Context->SegSs;
TrapFrame->Cs = Context->SegCs;
TrapFrame->Eip = Context->Eip;
/* Check if we went through a V86 switch */
if ((Context->EFlags & X86_EFLAGS_VM) !=
(TrapFrame->Eflags & X86_EFLAGS_VM))
{
/* We did, remember this for later */
V86Switch = TRUE;
}
/* Copy EFLAGS. FIXME: Needs to be sanitized */
TrapFrame->Eflags = Context->EFlags;
/* Copy EBP and EIP */
TrapFrame->Ebp = Context->Ebp;
TrapFrame->Eip = Context->Eip;
/* Check if we were in V86 Mode */
if (TrapFrame->Eflags & X86_EFLAGS_VM)
{
/* Simply copy the CS value */
TrapFrame->Cs = Context->SegCs;
}
else
{
/* We weren't in V86, so sanitize the CS (FIXME!) */
TrapFrame->Cs = Context->SegCs;
/* Don't let it under 8, that's invalid */
if ((PreviousMode !=KernelMode) && (TrapFrame->Cs < 8))
{
/* Force it to User CS */
TrapFrame->Cs = USER_CS;
}
}
/* Handle SS Specially for validation */
KiSsToTrapFrame(TrapFrame, Context->SegSs);
/* Write ESP back; take into account Edited Trap Frames */
KiEspToTrapFrame(TrapFrame, Context->Esp);
/* Handle our V86 Bias if we went through a switch */
if (V86Switch) Ki386AdjustEsp0(TrapFrame);
}
/* Process the Integer Registers */
@ -597,21 +752,62 @@ KeContextToTrapFrame(PCONTEXT Context,
/* Process the Context Segments */
if ((Context->ContextFlags & CONTEXT_SEGMENTS) == CONTEXT_SEGMENTS)
{
TrapFrame->Ds = Context->SegDs;
TrapFrame->Es = Context->SegEs;
TrapFrame->Fs = Context->SegFs;
TrapFrame->Gs = Context->SegGs;
/* Check if we were in V86 Mode */
if (TrapFrame->Eflags & X86_EFLAGS_VM)
{
/* Copy the V86 Segments directlry */
TrapFrame->V86_Ds = Context->SegDs;
TrapFrame->V86_Es = Context->SegEs;
TrapFrame->V86_Fs = Context->SegFs;
TrapFrame->V86_Gs = Context->SegGs;
}
else if (!(TrapFrame->Cs & 1))
{
/* For user mode, write the values directly */
TrapFrame->Ds = USER_DS;
TrapFrame->Es = USER_DS;
TrapFrame->Fs = Context->SegFs;
KEBUGCHECK(0);
TrapFrame->Gs = 0;
}
else
{
/* For kernel-mode, return the values */
TrapFrame->Ds = Context->SegDs;
TrapFrame->Es = Context->SegEs;
TrapFrame->Fs = Context->SegFs;
/* Handle GS specially */
if (TrapFrame->Cs == USER_CS)
{
/* Don't use it, if user */
TrapFrame->Gs = 0;
}
else
{
/* Copy it if kernel */
TrapFrame->Gs = Context->SegGs;
}
}
}
/* Handle the Debug Registers */
if ((Context->ContextFlags & CONTEXT_DEBUG_REGISTERS) == CONTEXT_DEBUG_REGISTERS)
{
/* FIXME: All these should be sanitized */
TrapFrame->Dr0 = Context->Dr0;
TrapFrame->Dr1 = Context->Dr1;
TrapFrame->Dr2 = Context->Dr2;
TrapFrame->Dr3 = Context->Dr3;
TrapFrame->Dr6 = Context->Dr6;
TrapFrame->Dr7 = Context->Dr7;
/* Check if usermode */
if (PreviousMode != KernelMode)
{
/* Set the Debug Flag */
KeGetCurrentThread()->DebugActive = (Context->Dr7 & DR7_ACTIVE);
}
}
/* Handle FPU and Extended Registers */
@ -619,51 +815,90 @@ KeContextToTrapFrame(PCONTEXT Context,
}
VOID
KeTrapFrameToContext(PKTRAP_FRAME TrapFrame,
PCONTEXT Context)
NTAPI
KeTrapFrameToContext(IN PKTRAP_FRAME TrapFrame,
IN PKEXCEPTION_FRAME ExceptionFrame,
IN OUT PCONTEXT Context)
{
if ((Context->ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL)
{
Context->SegSs = TrapFrame->Ss;
Context->Esp = TrapFrame->Esp;
Context->SegCs = TrapFrame->Cs;
Context->Eip = TrapFrame->Eip;
Context->EFlags = TrapFrame->Eflags;
Context->Ebp = TrapFrame->Ebp;
}
if ((Context->ContextFlags & CONTEXT_INTEGER) == CONTEXT_INTEGER)
{
Context->Eax = TrapFrame->Eax;
Context->Ebx = TrapFrame->Ebx;
Context->Ecx = TrapFrame->Ecx;
/*
* NOTE: In the trap frame which is built on entry to a system
* call TrapFrame->Edx will actually hold the address of the
* previous TrapFrame. I don't believe leaking this information
* has security implications. Also EDX holds the address of the
* arguments to the system call in progress so it isn't of much
* interest to the debugger.
*/
Context->Edx = TrapFrame->Edx;
Context->Esi = TrapFrame->Esi;
Context->Edi = TrapFrame->Edi;
}
if ((Context->ContextFlags & CONTEXT_SEGMENTS) == CONTEXT_SEGMENTS)
{
Context->SegDs = TrapFrame->Ds;
Context->SegEs = TrapFrame->Es;
Context->SegFs = TrapFrame->Fs;
Context->SegGs = TrapFrame->Gs;
}
/* Start with the Control flags */
if ((Context->ContextFlags & CONTEXT_CONTROL) == CONTEXT_CONTROL)
{
/* EBP, EIP and EFLAGS */
Context->Ebp = TrapFrame->Ebp;
Context->Eip = TrapFrame->Eip;
Context->EFlags = TrapFrame->Eflags;
/* Return the correct CS */
if (!(TrapFrame->Cs & FRAME_EDITED) &&
!(TrapFrame->Eflags & X86_EFLAGS_VM))
{
/* Get it from the Temp location */
Context->SegCs = TrapFrame->TempCs & 0xFFFF;
}
else
{
/* Return it directly */
Context->SegCs = TrapFrame->Cs & 0xFFFF;
}
/* Get the Ss and ESP */
Context->SegSs = KiSsFromTrapFrame(TrapFrame);
Context->Esp = KiEspFromTrapFrame(TrapFrame);
}
/* Handle the Segments */
if ((Context->ContextFlags & CONTEXT_SEGMENTS) == CONTEXT_SEGMENTS)
{
/* Do V86 Mode first */
if (TrapFrame->Eflags & X86_EFLAGS_VM)
{
/* Return from the V86 location */
Context->SegGs = TrapFrame->V86_Gs & 0xFFFF;
Context->SegFs = TrapFrame->V86_Fs & 0xFFFF;
Context->SegEs = TrapFrame->V86_Es & 0xFFFF;
Context->SegDs = TrapFrame->V86_Ds & 0xFFFF;
}
else
{
/* Check if this was a Kernel Trap */
if (TrapFrame->Cs == KERNEL_CS)
{
/* Set valid selectors */
TrapFrame->Gs = 0;
TrapFrame->Fs = PCR_SELECTOR;
TrapFrame->Es = USER_DS;
TrapFrame->Ds = USER_DS;
}
/* Return the segments */
Context->SegGs = TrapFrame->Gs & 0xFFFF;
Context->SegFs = TrapFrame->Fs & 0xFFFF;
Context->SegEs = TrapFrame->Es & 0xFFFF;
Context->SegDs = TrapFrame->Ds & 0xFFFF;
}
}
/* Handle the simple registers */
if ((Context->ContextFlags & CONTEXT_INTEGER) == CONTEXT_INTEGER)
{
/* Return them directly */
Context->Eax = TrapFrame->Eax;
Context->Ebx = TrapFrame->Ebx;
Context->Ecx = TrapFrame->Ecx;
Context->Edx = TrapFrame->Edx;
Context->Esi = TrapFrame->Esi;
Context->Edi = TrapFrame->Edi;
}
if ((Context->ContextFlags & CONTEXT_DEBUG_REGISTERS) == CONTEXT_DEBUG_REGISTERS)
{
{
/*
* FIXME: Implement this case
*/
Context->ContextFlags &= (~CONTEXT_DEBUG_REGISTERS) | CONTEXT_i386;
}
if ((Context->ContextFlags & CONTEXT_FLOATING_POINT) == CONTEXT_FLOATING_POINT)
{
{
/*
* FIXME: Implement this case
*
@ -676,7 +911,7 @@ KeTrapFrameToContext(PKTRAP_FRAME TrapFrame,
}
#if 0
if ((Context->ContextFlags & CONTEXT_EXTENDED_REGISTERS) == CONTEXT_EXTENDED_REGISTERS)
{
{
/*
* FIXME: Investigate this
*
@ -931,7 +1166,7 @@ KiDispatchException(PEXCEPTION_RECORD ExceptionRecord,
ULONG_PTR Stack, NewStack;
ULONG Size;
BOOLEAN UserDispatch = FALSE;
DPRINT1("KiDispatchException() called\n");
DPRINT("KiDispatchException() called\n");
/* Increase number of Exception Dispatches */
KeGetCurrentPrcb()->KeExceptionDispatchCount++;
@ -947,7 +1182,7 @@ KiDispatchException(PEXCEPTION_RECORD ExceptionRecord,
}
/* Get a Context */
KeTrapFrameToContext(TrapFrame, &Context);
KeTrapFrameToContext(TrapFrame, ExceptionFrame, &Context);
/* Handle kernel-mode first, it's simpler */
if (PreviousMode == KernelMode)
@ -1017,7 +1252,7 @@ KiDispatchException(PEXCEPTION_RECORD ExceptionRecord,
/* Align context size and get stack pointer */
Size = (sizeof(CONTEXT) + 3) & ~3;
Stack = (Context.Esp & ~3) - Size;
DPRINT1("Stack: %lx\n", Stack);
DPRINT("Stack: %lx\n", Stack);
/* Probe stack and copy Context */
ProbeForWrite((PVOID)Stack, Size, sizeof(ULONG));
@ -1028,7 +1263,7 @@ KiDispatchException(PEXCEPTION_RECORD ExceptionRecord,
(EXCEPTION_MAXIMUM_PARAMETERS - ExceptionRecord->NumberParameters) *
sizeof(ULONG) + 3) & ~3;
NewStack = Stack - Size;
DPRINT1("NewStack: %lx\n", NewStack);
DPRINT("NewStack: %lx\n", NewStack);
/* Probe stack and copy exception record. Don't forget to add the two params */
ProbeForWrite((PVOID)(NewStack - 2 * sizeof(ULONG_PTR)),
@ -1041,7 +1276,7 @@ KiDispatchException(PEXCEPTION_RECORD ExceptionRecord,
*(PULONG_PTR)(NewStack - 2 * sizeof(ULONG_PTR)) = NewStack;
/* Set new Stack Pointer */
TrapFrame->Esp = NewStack - 2 * sizeof(ULONG_PTR);
KiEspToTrapFrame(TrapFrame, NewStack - 2 * sizeof(ULONG_PTR));
/* Set EIP to the User-mode Dispathcer */
TrapFrame->Eip = (ULONG)KeUserExceptionDispatcher;
@ -1073,7 +1308,7 @@ KiDispatchException(PEXCEPTION_RECORD ExceptionRecord,
Handled:
/* Convert the context back into Trap/Exception Frames */
KeContextToTrapFrame(&Context, NULL, TrapFrame);
KeContextToTrapFrame(&Context, NULL, TrapFrame, PreviousMode);
return;
}

View file

@ -528,7 +528,7 @@ KiHandleFpuFault(PKTRAP_FRAME Tf, ULONG ExceptionNr)
/* Fill the rest of the context */
Context->ContextFlags = CONTEXT_FULL;
KeTrapFrameToContext(Tf, Context);
KeTrapFrameToContext(Tf, NULL, Context);
Context->ContextFlags |= CONTEXT_FLOATING_POINT | CONTEXT_EXTENDED_REGISTERS;
/* Determine exception code */

File diff suppressed because it is too large Load diff

View file

@ -85,7 +85,7 @@ Ke386InitThreadWithContext(PKTHREAD Thread,
TrapFrame = &InitFrame->TrapFrame;
/* Set up a trap frame from the context. */
if (KeContextToTrapFrame(Context, NULL, TrapFrame))
if (KeContextToTrapFrame(Context, NULL, TrapFrame, UserMode))
{
Thread->NpxState = NPX_STATE_VALID;
}
@ -146,7 +146,9 @@ Ke386InitThreadWithContext(PKTHREAD Thread,
/* And set up the Context Switch Frame */
CtxSwitchFrame->RetEip = KiThreadStartup;
CtxSwitchFrame->Esp0 = (ULONG)Thread->InitialStack - sizeof(FX_SAVE_AREA);
CtxSwitchFrame->Esp0 = (ULONG_PTR)Thread->InitialStack -
sizeof(FX_SAVE_AREA) -
0x10;
CtxSwitchFrame->ExceptionList = (PVOID)0xFFFFFFFF;
/* Save back the new value of the kernel stack. */

View file

@ -10,6 +10,7 @@
#include <roscfg.h>
#include <ndk/asm.h>
#include <internal/i386/ke.h>
#include <ndk/i386/segment.h>
#define KernelMode 0
@ -374,4 +375,37 @@ _KiCoprocessorError@0:
/* Return to caller */
ret
.globl _Ki386AdjustEsp0@4
_Ki386AdjustEsp0@4:
/* Get the current thread */
mov eax, [fs:KPCR_CURRENT_THREAD]
/* Get trap frame and stack */
mov edx, [esp+4]
mov eax, [eax+KTHREAD_INITIAL_STACK]
/* Check if V86 */
test dword ptr [edx+KTRAP_FRAME_EFLAGS], X86_EFLAGS_VM
jnz NoAdjust
/* Bias the stack */
sub eax, KTRAP_FRAME_V86_GS - KTRAP_FRAME_SS
NoAdjust:
/* Skip FX Save Area */
sub eax, SIZEOF_FX_SAVE_AREA
/* Disable interrupts */
pushf
cli
/* Adjust ESP0 */
mov edx, [fs:KPCR_TSS]
mov ss:[edx+KTSS_ESP0], eax
/* Enable interrupts and return */
popf
ret 4
/* EOF */

View file

@ -36,11 +36,11 @@ ULONG KiPageFaultHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr)
ASSERT(ExceptionNr == 14);
/* Store the exception number in an unused field in the trap frame. */
Tf->DebugArgMark = (PVOID)14;
Tf->DebugArgMark = 14;
/* get the faulting address */
cr2 = Ke386GetCr2();
Tf->DebugPointer = (PVOID)cr2;
Tf->DebugPointer = cr2;
/* it's safe to enable interrupts after cr2 has been saved */
if (Tf->Eflags & (X86_EFLAGS_VM|X86_EFLAGS_IF))

View file

@ -22,6 +22,7 @@ typedef struct _GET_SET_CTX_CONTEXT {
KAPC Apc;
KEVENT Event;
CONTEXT Context;
KPROCESSOR_MODE Mode;
} GET_SET_CTX_CONTEXT, *PGET_SET_CTX_CONTEXT;
@ -42,22 +43,24 @@ PspGetOrSetContextKernelRoutine(PKAPC Apc,
PGET_SET_CTX_CONTEXT GetSetContext;
PKEVENT Event;
PCONTEXT Context;
KPROCESSOR_MODE Mode;
/* Get the Context Structure */
GetSetContext = CONTAINING_RECORD(Apc, GET_SET_CTX_CONTEXT, Apc);
Context = &GetSetContext->Context;
Event = &GetSetContext->Event;
Mode = GetSetContext->Mode;
/* Check if it's a set or get */
if (SystemArgument1) {
/* Get the Context */
KeTrapFrameToContext(KeGetCurrentThread()->TrapFrame, Context);
KeTrapFrameToContext(KeGetCurrentThread()->TrapFrame, NULL, Context);
} else {
/* Set the Context */
KeContextToTrapFrame(Context, NULL, KeGetCurrentThread()->TrapFrame);
KeContextToTrapFrame(Context, NULL, KeGetCurrentThread()->TrapFrame, Mode);
}
/* Notify the Native API that we are done */
@ -111,7 +114,7 @@ NtGetContextThread(IN HANDLE ThreadHandle,
* I don't know if trying to get your own context makes much
* sense but we can handle it more efficently.
*/
KeTrapFrameToContext(Thread->Tcb.TrapFrame, &GetSetContext.Context);
KeTrapFrameToContext(Thread->Tcb.TrapFrame, NULL, &GetSetContext.Context);
} else {
@ -120,6 +123,9 @@ NtGetContextThread(IN HANDLE ThreadHandle,
NotificationEvent,
FALSE);
/* Set the previous mode */
GetSetContext.Mode = PreviousMode;
/* Initialize the APC */
KeInitializeApc(&GetSetContext.Apc,
&Thread->Tcb,
@ -221,7 +227,7 @@ NtSetContextThread(IN HANDLE ThreadHandle,
* I don't know if trying to get your own context makes much
* sense but we can handle it more efficently.
*/
KeContextToTrapFrame(&GetSetContext.Context, NULL, Thread->Tcb.TrapFrame);
KeContextToTrapFrame(&GetSetContext.Context, NULL, Thread->Tcb.TrapFrame, PreviousMode);
} else {
@ -230,6 +236,9 @@ NtSetContextThread(IN HANDLE ThreadHandle,
NotificationEvent,
FALSE);
/* Set the previous mode */
GetSetContext.Mode = PreviousMode;
/* Initialize the APC */
KeInitializeApc(&GetSetContext.Apc,
&Thread->Tcb,