Modified: trunk/reactos/lib/ntdll/ldr/startup.c
Modified: trunk/reactos/lib/rtl/i386/exception.c
Modified: trunk/reactos/ntoskrnl/ex/init.c
Modified: trunk/reactos/ntoskrnl/include/internal/i386/ke.h
Modified: trunk/reactos/ntoskrnl/include/internal/ke.h
Modified: trunk/reactos/ntoskrnl/kd/wrappers/gdbstub.c
Modified: trunk/reactos/ntoskrnl/kdbg/kdb.c
Modified: trunk/reactos/ntoskrnl/kdbg/kdb_cli.c
Modified: trunk/reactos/ntoskrnl/ke/apc.c
Modified: trunk/reactos/ntoskrnl/ke/exception.c
Modified: trunk/reactos/ntoskrnl/ke/i386/ctxswitch.S
Modified: trunk/reactos/ntoskrnl/ke/i386/exp.c
Modified: trunk/reactos/ntoskrnl/ke/i386/fpu.c
Modified: trunk/reactos/ntoskrnl/ke/i386/syscall.S
Modified: trunk/reactos/ntoskrnl/ke/i386/thread.c
Modified: trunk/reactos/ntoskrnl/ke/i386/trap.s
Modified: trunk/reactos/ntoskrnl/mm/i386/pfault.c
Modified: trunk/reactos/ntoskrnl/ps/debug.c
--- trunk/reactos/lib/ntdll/ldr/startup.c 2005-09-13 19:11:37 UTC (rev 17837)
+++ trunk/reactos/lib/ntdll/ldr/startup.c 2005-09-13 19:33:49 UTC (rev 17838)
@@ -256,13 +256,13 @@
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 @@
/* 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 @@
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);
--- trunk/reactos/lib/rtl/i386/exception.c 2005-09-13 19:11:37 UTC (rev 17837)
+++ trunk/reactos/lib/rtl/i386/exception.c 2005-09-13 19:33:49 UTC (rev 17838)
@@ -165,7 +165,7 @@
}
/* Unhandled, return false */
- DPRINT1("FALSE:(\n");
+ DPRINT1("FALSE\n");
return FALSE;
}
--- trunk/reactos/ntoskrnl/ex/init.c 2005-09-13 19:11:37 UTC (rev 17837)
+++ trunk/reactos/ntoskrnl/ex/init.c 2005-09-13 19:33:49 UTC (rev 17838)
@@ -241,7 +241,6 @@
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);
--- trunk/reactos/ntoskrnl/include/internal/i386/ke.h 2005-09-13 19:11:37 UTC (rev 17837)
+++ trunk/reactos/ntoskrnl/include/internal/i386/ke.h 2005-09-13 19:33:49 UTC (rev 17838)
@@ -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
--- trunk/reactos/ntoskrnl/include/internal/ke.h 2005-09-13 19:11:37 UTC (rev 17837)
+++ trunk/reactos/ntoskrnl/include/internal/ke.h 2005-09-13 19:33:49 UTC (rev 17838)
@@ -287,7 +287,10 @@
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,9 +371,12 @@
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
KePrepareForApplicationProcessorInit(ULONG id);
--- trunk/reactos/ntoskrnl/kd/wrappers/gdbstub.c 2005-09-13 19:11:37 UTC (rev 17837)
+++ trunk/reactos/ntoskrnl/kd/wrappers/gdbstub.c 2005-09-13 19:33:49 UTC (rev 17838)
@@ -1321,7 +1321,7 @@
#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 @@
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);
--- trunk/reactos/ntoskrnl/kdbg/kdb.c 2005-09-13 19:11:37 UTC (rev 17837)
+++ trunk/reactos/ntoskrnl/kdbg/kdb.c 2005-09-13 19:33:49 UTC (rev 17838)
@@ -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 @@
"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 @@
"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 @@
/* 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 */
}
--- trunk/reactos/ntoskrnl/kdbg/kdb_cli.c 2005-09-13 19:11:37 UTC (rev 17837)
+++ trunk/reactos/ntoskrnl/kdbg/kdb_cli.c 2005-09-13 19:33:49 UTC (rev 17838)
@@ -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
--- trunk/reactos/ntoskrnl/ke/apc.c 2005-09-13 19:11:37 UTC (rev 17837)
+++ trunk/reactos/ntoskrnl/ke/apc.c 2005-09-13 19:33:49 UTC (rev 17838)
@@ -812,7 +812,7 @@
/* Save the full context */
Context.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS;
- KeTrapFrameToContext(TrapFrame, &Context);
+ KeTrapFrameToContext(TrapFrame, ExceptionFrame, &Context);
/* Protect with SEH */
_SEH_TRY
--- trunk/reactos/ntoskrnl/ke/exception.c 2005-09-13 19:11:37 UTC (rev 17837)
+++ trunk/reactos/ntoskrnl/ke/exception.c 2005-09-13 19:33:49 UTC (rev 17838)
@@ -28,7 +28,7 @@
Context = &LocalContext;
/* Convert the context into Exception/Trap Frames */
- KeContextToTrapFrame(&LocalContext, ExceptionFrame, TrapFrame);
+ KeContextToTrapFrame(&LocalContext, ExceptionFrame, TrapFrame, UserMode);
}
NTSTATUS
@@ -62,7 +62,7 @@
else
{
/* Convert the context into Exception/Trap Frames */
- KeContextToTrapFrame(Context, ExceptionFrame, TrapFrame);
+ KeContextToTrapFrame(Context, ExceptionFrame, TrapFrame, KernelMode);
}
}
_SEH_HANDLE
@@ -142,7 +142,7 @@
if (NT_SUCCESS(Status))
{
/* Convert the context record */
- KeContextToTrapFrame(Context, ExceptionFrame, TrapFrame);
+ KeContextToTrapFrame(Context, ExceptionFrame, TrapFrame, PreviousMode);
/* Dispatch the exception */
KiDispatchException(ExceptionRecord,
--- trunk/reactos/ntoskrnl/ke/i386/ctxswitch.S 2005-09-13 19:11:37 UTC (rev 17837)
+++ trunk/reactos/ntoskrnl/ke/i386/ctxswitch.S 2005-09-13 19:33:49 UTC (rev 17838)
@@ -114,7 +114,7 @@
.globl @KiSwapContextInternal@0
@KiSwapContextInternal@0:
#ifdef KDBG
- jmp SaveTrapFrameForKDB
+ //jmp SaveTrapFrameForKDB
SaveTrapFrameForKDB_Return:
#endif
@@ -130,12 +130,14 @@
/* 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 @@
/* 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]
--- trunk/reactos/ntoskrnl/ke/i386/exp.c 2005-09-13 19:11:37 UTC (rev 17837)
+++ trunk/reactos/ntoskrnl/ke/i386/exp.c 2005-09-13 19:33:49 UTC (rev 17838)
@@ -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 @@
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 @@
}
}
+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
-STDCALL
-KeContextToTrapFrame(PCONTEXT Context,
- PKEXCEPTION_FRAME ExceptionFrame,
- PKTRAP_FRAME TrapFrame)
+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 @@
/* 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 @@
}
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 @@
}
#if 0
if ((Context->ContextFlags & CONTEXT_EXTENDED_REGISTERS) == CONTEXT_EXTENDED_REGISTERS)
- {
+ {
/*
* FIXME: Investigate this
*
@@ -931,7 +1166,7 @@
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 @@
}
/* Get a Context */
- KeTrapFrameToContext(TrapFrame, &Context);
+ KeTrapFrameToContext(TrapFrame, ExceptionFrame, &Context);
/* Handle kernel-mode first, it's simpler */
if (PreviousMode == KernelMode)
@@ -1017,7 +1252,7 @@
/* 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 @@
(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 @@
*(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 @@
Handled:
/* Convert the context back into Trap/Exception Frames */
- KeContextToTrapFrame(&Context, NULL, TrapFrame);
+ KeContextToTrapFrame(&Context, NULL, TrapFrame, PreviousMode);
return;
}
--- trunk/reactos/ntoskrnl/ke/i386/fpu.c 2005-09-13 19:11:37 UTC (rev 17837)
+++ trunk/reactos/ntoskrnl/ke/i386/fpu.c 2005-09-13 19:33:49 UTC (rev 17838)
@@ -528,7 +528,7 @@
/* 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 */
--- trunk/reactos/ntoskrnl/ke/i386/syscall.S 2005-09-13 19:11:37 UTC (rev 17837)
+++ trunk/reactos/ntoskrnl/ke/i386/syscall.S 2005-09-13 19:33:49 UTC (rev 17838)
@@ -1,13 +1,8 @@
-/* $Id$
- *
+/*
* FILE: ntoskrnl/ke/i386/syscall.S
* COPYRIGHT: See COPYING in the top level directory
* PURPOSE: System Call Handler
* PROGRAMMER: Alex Ionescu (alex@relsoft.net)
- * UPDATE HISTORY:
- * ??-??-??: Original Version - David Welch(?)
- * 13-01-05: Complete rewrite, added support for SYSENTER, direct kmode syscalls
- * and re-wrote most of handler code. - Alex Ionescu
*/
#include <roscfg.h>
@@ -16,275 +11,491 @@
#include <ndk/i386/segment.h>
#define UserMode (1)
+#define STATUS_INVALID_SYSTEM_SERVICE 0xC000001C
-.globl KeReturnFromSystemCallWithHook
.globl _KiServiceExit
.globl _KiServiceExit2
.globl _KiFastCallEntry
.globl _KiSystemService
.globl _KiDebugService
+.intel_syntax noprefix
+/*
+ * NOTE: I will create some macros for trap entry and exit,
+ * DR* register restoration, modified frame exit, etc, if GAS
+ * allows it/I find a way how. This would remove a lot of
+ * duplicated code in this file plus the other irq/trap asm files.
+ * I think this is similar to what NT does, if you look at teh
+ * Dr_kit*_a functions which look auto-generated.
+ */
+
+/*
+ * There are 3 main types of Trap Exits:
+ *
+ * - KiServiceExit
+ * - Clear interrupt flag
+ * - Common User APC Dispatching
+ * - Common exit code; segments and volatiles are not restored
+ * You use this for System Call return, when volatiles are irrelevant.
+ * (NtContinue, NtRaiseException, KiCallUserMode and all System Call returns)
+ *
+ * - KiServiceExit2
+ * - Clear interrupt flag
+ * - Common User APC Dispatching
+ * - Common exit code; the entire frame is restored.
+ * You use this when volatiles and other registers need to be restored.
+ * For example, if debugging is active (NtContinue, NtRaiseException).
+ *
+ * - Kei386EoiHelper
+ * - Clear interrupt flag
+ * - Common User APC Dispatching
+ * - Common exit code; the entire frame is restored but *NOT* the Previous Mode
+ * You use this in the same context as KiServiceExit2, but when the Previous Mode
+ * should be tampered with. Clearly, as its name suggests, this routine is mostly
+ * useful for End Of Interrupts.
+ * Note that this routine is EXPORTED.
+ * Note that this routine must called by a JMP, not a CALL.
+ */
+
+/*
+ * The common exit code has 3 modes of operation:
+ * - Whether or not to restore segments
+ * - Whether or not to restore volatiles
+ * - Whether or not to restore the previous mode
+ * All these are exemplified by the 3 trap exits shown above
+ */
+
+/*
+ * There is also common Debug Code present in the common exit code, which
+ * in turn calls common code to save the debug registers
+ */
+
+ /*
+ * FIXMEs:
+ * - Fix Win32k Callbacks so we can optimize stack usage.
+ * - Dig in trap code and see why we need to push/pop the segments,
+ * which -shouldn't- be needed on syscalls; one of the things
+ * missing for this to work is lazy loading in the GPF handler,
+ * but there are other things to consider.
+ * - Use macros and merge with trap.s nicely
+ */
+
+/*
+ * Entries will be discussed later.
+ */
+
+ /*** This file is a mess; it is being worked on. Please contact Alex:
+ *** alex@relsoft.net if you want to make any changes to it before this
+ *** message goes away
+ */
+
+/* FUNCTIONS ***************************************************************/
+
+BadStack:
+
+ /* Restore ESP0 stack */
+ mov ecx, [fs:KPCR_TSS]
+ mov esp, ss:[ecx+KTSS_ESP0]
+
+ /* FIXME: Generate Trap 6*/
+ int 3
+
_KiFastCallEntry:
+// ==================== UNIQUE SYSENTER STUB. DO NOT DUPLICATE ============//
/* Set FS to PCR */
- movl $PCR_SELECTOR, %ecx
- movw %cx, %fs
+ mov ecx, PCR_SELECTOR
+ mov fs, cx
+ /* Set DS/ES to Kernel Selector */
+ mov ecx, KERNEL_DS
+ mov ds, cx
+ mov es, cx
+
/* Set the current stack to Kernel Stack */
- movl %fs:KPCR_TSS, %ecx
- movl %ss:KTSS_ESP0(%ecx), %ecx
- movl %ecx, %esp
+ mov ecx, [fs:KPCR_TSS]
+ mov esp, ss:[ecx+KTSS_ESP0]
+ /*
+ * ^^^^^ Normally we should be able to use KTHREAD.InitialStack - sizeof
+ * KTRAP_FRAME - sizeof(NPX_AREA) and that will give us exactly
+ * our esp (ie: ebp == esp by the way the system is organized).
+ * This didn't work until I added v86m trap frame bias, which was
+ * needed anways. It works NICELY until we hit a Win32K Callback,
+ * which also messes up a lea esp, [ebp+...] below. It seems the
+ * stack for callbacks isn't properly set up (it's missing sizeof
+ * KTRAP_FRAME), which is understandable since the whole code is
+ * messed up and smashes new stacks instead of using the kernel
+ * assigned one.
+ */
/* Set up a fake INT Stack. */
- pushl $USER_DS
- pushl %edx /* Ring 3 SS:ESP */
- pushfl
- orl $X86_EFLAGS_IF, (%esp) /* Re-enable IRQs in EFLAGS, to fake INT */
- pushl $USER_CS
- pushl $KUSER_SHARED_SYSCALL_RET
+ push USER_DS
+ push edx /* Ring 3 SS:ESP */
+ pushf /* Ring 3 EFLAGS */
+ push 2 /* Ring 0 EFLAGS */
+ add edx, 8 /* Skip user parameter list */
+ popf /* Set our EFLAGS */
+ or dword ptr [esp], X86_EFLAGS_IF /* Re-enable IRQs in EFLAGS, to fake INT */
+ push USER_CS
[truncated at 1000 lines; 1168 more skipped]