- Use MmUserProbeAddress in the system call handler to verify the
parametes we got from user-mode are valid and return
STATUS_ACCESS_VIOLATION if the check fails.
- Handle failure after PsConvertToGuiThread and return
STATUS_INVALID_SYSTEM_SERVICE and/or FALSE and/or -1 on failure.
- Made MCE/XMMI interrupts unexpected on-boot.
- Removed KiTrapUnknown and used KiTrap0F (15) instead, which is the
generic unexpected handler.
Modified: trunk/reactos/include/ndk/asm.h
Modified: trunk/reactos/ntoskrnl/ke/i386/trap.s
_____
Modified: trunk/reactos/include/ndk/asm.h
--- trunk/reactos/include/ndk/asm.h 2006-01-17 22:34:20 UTC (rev
20941)
+++ trunk/reactos/include/ndk/asm.h 2006-01-17 22:41:39 UTC (rev
20942)
@@ -357,10 +357,12 @@
// NTSTATUS and Bugcheck Codes
//
#ifdef __ASM__
+#define STATUS_ACCESS_VIOLATION 0xC0000005
#define STATUS_INVALID_SYSTEM_SERVICE 0xC000001C
#define STATUS_NO_CALLBACK_ACTIVE 0xC0000258
-#define APC_INDEX_MISMATCH 1
+#define APC_INDEX_MISMATCH 0x01
#define IRQL_GT_ZERO_AT_SYSTEM_SERVICE 0x4A
+#define UNEXPECTED_KERNEL_MODE_TRAP 0x7F
#endif
//
_____
Modified: trunk/reactos/ntoskrnl/ke/i386/trap.s
--- trunk/reactos/ntoskrnl/ke/i386/trap.s 2006-01-17 22:34:20 UTC
(rev 20941)
+++ trunk/reactos/ntoskrnl/ke/i386/trap.s 2006-01-17 22:41:39 UTC
(rev 20942)
@@ -16,8 +16,6 @@
* FIXMEs:
* - Figure out why ES/DS gets messed up in VMWare, when doing
KiServiceExit only,
* and only when called from user-mode, and returning to
user-mode.
- * - Use MmProbe when copying arguments to syscall.
- * - Handle failure after PsConvertToGuiThread.
* - Figure out what the DEBUGEIP hack is for and how it can
be moved away.
* - Add DR macro/save and VM macro/save.
* - Implement KiCallbackReturn, KiGetTickCount,
KiRaiseAssertion.
@@ -43,22 +41,22 @@
idt _KiTrap12, INT_32_DPL0 /* INT 0C: Stack Fault Exception
(#SS) */
idt _KiTrap13, INT_32_DPL0 /* INT 0D: General Protection (#GP)
*/
idt _KiTrap14, INT_32_DPL0 /* INT 0E: Page-Fault Exception
(#PF) */
-idt _KiTrap15, INT_32_DPL0 /* INT 0F: RESERVED
*/
+idt _KiTrap15, INT_32_DPL0 /* INT 0F: RESERVED [FIXME: HBIRR
HACK] */
idt _KiTrap16, INT_32_DPL0 /* INT 10: x87 FPU Error (#MF)
*/
idt _KiTrap17, INT_32_DPL0 /* INT 11: Align Check Exception
(#AC) */
-idt _KiTrap18, INT_32_DPL0 /* INT 12: Machine Check Exception
(#MC)*/
-idt _KiTrap19, INT_32_DPL0 /* INT 13: SIMD FPU Exception (#XF)
*/
+idt _KiTrap0F, INT_32_DPL0 /* INT 12: Machine Check Exception
(#MC)*/
+idt _KiTrap0F, INT_32_DPL0 /* INT 13: SIMD FPU Exception (#XF)
*/
.rept 22
-idt _KiTrapUnknown, INT_32_DPL0 /* INT 14-29: UNDEFINED INTERRUPTS
*/
+idt _KiTrap0F, INT_32_DPL0 /* INT 14-29: UNDEFINED INTERRUPTS
*/
.endr
idt _KiGetTickCount, INT_32_DPL3 /* INT 2A: Get Tick Count Handler
*/
idt _KiCallbackReturn, INT_32_DPL3 /* INT 2B: User-Mode Callback
Return */
idt _KiRaiseAssertion, INT_32_DPL3 /* INT 2C: Debug Assertion Handler
*/
idt _KiDebugService, INT_32_DPL3 /* INT 2D: Debug Service Handler
*/
idt _KiSystemService, INT_32_DPL3 /* INT 2E: System Call Service
Handler */
-idt _KiTrapUnknown, INT_32_DPL0 /* INT 2F: RESERVED
*/
+idt _KiTrap0F, INT_32_DPL0 /* INT 2F: RESERVED
*/
.rept 220
-idt _KiTrapUnknown, INT_32_DPL0 /* INT 30-FF: UNDEFINED INTERRUPTS
*/
+idt _KiTrap0F, INT_32_DPL0 /* INT 30-FF: UNDEFINED INTERRUPTS
*/
.endr
/* System call entrypoints:
*/
@@ -271,33 +269,28 @@
/* Allocate space on our stack */
sub esp, ecx
- /*
- * Copy the arguments from the user stack to our stack
- * FIXME: This needs to be probed with MmSystemRangeStart
- */
+ /* Set the size of the arguments and the destination */
shr ecx, 2
mov edi, esp
+
+ /* Make sure we're within the User Probe Address */
+ cmp esi, _MmUserProbeAddress
+ jnb AccessViolation
+
+CopyParams:
+ /* Copy the parameters */
rep movsd
#ifdef DBG
-
- /* Make sure this isn't a user-mode call at elevated IRQL */
- test byte ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
- jz SkipCheck
- call _KeGetCurrentIrql@0
- or al, al
- jnz InvalidIrql
-
/*
* The following lines are for the benefit of GDB. It will see the
return
* address of the "call ebx" below, find the last label before it
and
* thinks that that's the start of the function. It will then check
to see
- * if it starts with a standard function prolog (push ebp, mov
ebp,esp).
+ * if it starts with a standard function prolog (push ebp, mov
ebp,esp1).
* When that standard function prolog is not found, it will stop
the
* stack backtrace. Since we do want to backtrace into usermode,
let's
* make GDB happy and create a standard prolog.
*/
-SkipCheck:
KiSystemService:
push ebp
mov ebp,esp
@@ -307,10 +300,11 @@
/* Do the System Call */
call ebx
+AfterSysCall:
#ifdef DBG
/* Make sure the user-mode call didn't return at elevated IRQL */
test byte ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
- jz SkipCheck2
+ jz SkipCheck
mov esi, eax /* We need to save the syscall's return
val */
call _KeGetCurrentIrql@0
or al, al
@@ -329,7 +323,7 @@
jnz InvalidIndex
#endif
-SkipCheck2:
+SkipCheck:
/* Deallocate the kernel stack frame */
mov esp, ebp
@@ -363,7 +357,7 @@
KiBBTUnexpectedRange:
/* If this isn't a Win32K call, fail */
- cmp ecx, 0x10
+ cmp ecx, SERVICE_TABLE_TEST
jne InvalidCall
/* Set up Win32K Table */
@@ -371,7 +365,10 @@
push ebx
call _PsConvertToGuiThread@0
- /* FIXME: Handle failure */
+ /* Check return code */
+ or eax, eax
+
+ /* Restore registers */
pop eax
pop edx
@@ -379,15 +376,53 @@
mov ebp, esp
mov [esi+KTHREAD_TRAP_FRAME], ebp
- /* Try the Call again */
- jmp SharedCode
+ /* Try the Call again, if we suceeded */
+ jz SharedCode
+ /*
+ * The Shadow Table should have a special byte table which tells us
+ * whether we should return FALSE, -1 or
STATUS_INVALID_SYSTEM_SERVICE.
+ */
+
+ /* Get the table limit and base */
+ lea edx, _KeServiceDescriptorTableShadow + SERVICE_TABLE_TEST
+ mov ecx, [edx+SERVICE_DESCRIPTOR_LIMIT]
+ mov edx, [edx+SERVICE_DESCRIPTOR_BASE]
+
+ /* Get the table address and add our index into the array */
+ lea edx, [edx+ecx*4]
+ and eax, SERVICE_NUMBER_MASK
+ add edx, eax
+
+ /* Find out what we should return */
+ movsx eax, byte ptr [edx]
+ or eax, eax
+
+ /* Return either 0 or -1, we've set it in EAX */
+ jle KeReturnFromSystemCall
+
+ /* Set STATUS_INVALID_SYSTEM_SERVICE */
+ mov eax, STATUS_INVALID_SYSTEM_SERVICE
+ jmp KeReturnFromSystemCall
+
InvalidCall:
/* Invalid System Call */
mov eax, STATUS_INVALID_SYSTEM_SERVICE
jmp KeReturnFromSystemCall
+AccessViolation:
+
+ /* Check if this came from kernel-mode */
+ test byte ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
+
+ /* It's fine, go ahead with it */
+ jz CopyParams
+
+ /* Caller sent invalid parameters, fail here */
+ mov eax, STATUS_ACCESS_VIOLATION
+ jmp AfterSysCall
+
BadStack:
/* Restore ESP0 stack */
@@ -974,57 +1009,34 @@
jne _Kei386EoiHelper@0
jmp _KiV86Complete
-_KiTrap18:
+_KiTrap0F:
/* Push error code */
push 0
/* Enter trap */
- TRAP_PROLOG(18)
+ TRAP_PROLOG(15)
+ sti
- /* Call the C exception handler */
- push 18
- push ebp
- call _KiTrapHandler
- add esp, 8
+ /* Raise a fatal exception */
+ mov eax, 15
+ jmp _KiSystemFatalException
- /* Check for v86 recovery */
- cmp eax, 1
+.func KiSystemFatalException
+_KiSystemFatalException:
- /* Return to caller */
- jne _Kei386EoiHelper@0
- jmp _KiV86Complete
-
-_KiTrap19:
- /* Push error code */
- push 0
-
- /* Enter trap */
- TRAP_PROLOG(19)
-
- /* Call the C exception handler */
- push 19
+ /* Push the trap frame */
push ebp
- call _KiTrapHandler
- add esp, 8
- /* Check for v86 recovery */
- cmp eax, 1
-
- /* Return to caller */
- jne _Kei386EoiHelper@0
- jmp _KiV86Complete
-
-_KiTrapUnknown:
- /* Push error code */
+ /* Push empty parameters */
push 0
+ push 0
+ push 0
- /* Enter trap */
- TRAP_PROLOG(255)
+ /* Push trap number and bugcheck code */
+ push eax
+ push UNEXPECTED_KERNEL_MODE_TRAP
+ call _KeBugCheckWithTf@24
+ ret
+.endfunc
- /* Check for v86 recovery */
- cmp eax, 1
- /* Return to caller */
- jne _Kei386EoiHelper@0
- jmp _KiV86Complete
-
- Move some assembly functions around in better suited locations.
- Merge syscall.S and trap.S into trap.S, and nicely document the
software interrupt table that we service, as well as special cases.
Modified: trunk/reactos/ntoskrnl/ke/i386/cpu.S
Modified: trunk/reactos/ntoskrnl/ke/i386/ctxswitch.S
Deleted: trunk/reactos/ntoskrnl/ke/i386/syscall.S
Modified: trunk/reactos/ntoskrnl/ke/i386/trap.s
Modified: trunk/reactos/ntoskrnl/ntoskrnl.xml
_____
Modified: trunk/reactos/ntoskrnl/ke/i386/cpu.S
--- trunk/reactos/ntoskrnl/ke/i386/cpu.S 2006-01-17 05:54:35 UTC
(rev 20935)
+++ trunk/reactos/ntoskrnl/ke/i386/cpu.S 2006-01-17 06:36:35 UTC
(rev 20936)
@@ -46,3 +46,26 @@
mov cr3, eax
ret
.endfunc
+
+.globl _KiCoprocessorError@0
+.func KiCoprocessorError@0
+_KiCoprocessorError@0:
+
+ /* Get the NPX Thread's Initial stack */
+ mov eax, [fs:KPCR_NPX_THREAD]
+ mov eax, [eax+KTHREAD_INITIAL_STACK]
+
+ /* Make space for the FPU Save area */
+ sub eax, SIZEOF_FX_SAVE_AREA
+
+ /* Set the CR0 State */
+ mov dword ptr [eax+FN_CR0_NPX_STATE], 8
+
+ /* Update it */
+ mov eax, cr0
+ or eax, 8
+ mov cr0, eax
+
+ /* Return to caller */
+ ret
+.endfunc
_____
Modified: trunk/reactos/ntoskrnl/ke/i386/ctxswitch.S
--- trunk/reactos/ntoskrnl/ke/i386/ctxswitch.S 2006-01-17 05:54:35 UTC
(rev 20935)
+++ trunk/reactos/ntoskrnl/ke/i386/ctxswitch.S 2006-01-17 06:36:35 UTC
(rev 20936)
@@ -329,3 +329,37 @@
add esp, 4 * 4
ret
+.globl _Ki386AdjustEsp0@4
+.func 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], EFLAGS_V86_MASK
+ jnz 1f
+
+ /* Bias the stack */
+ sub eax, KTRAP_FRAME_V86_GS - KTRAP_FRAME_SS
+
+1:
+ /* 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
+.endfunc
_____
Deleted: trunk/reactos/ntoskrnl/ke/i386/syscall.S
--- trunk/reactos/ntoskrnl/ke/i386/syscall.S 2006-01-17 05:54:35 UTC
(rev 20935)
+++ trunk/reactos/ntoskrnl/ke/i386/syscall.S 2006-01-17 06:36:35 UTC
(rev 20936)
@@ -1,584 +0,0 @@
-/*
- * FILE: ntoskrnl/ke/i386/syscall.S
- * COPYRIGHT: See COPYING in the top level directory
- * PURPOSE: System Call Handler
- * PROGRAMMER: Alex Ionescu (alex(a)relsoft.net)
- */
-
-#include <asm.h>
-#include <internal/i386/asmmacro.S>
-
-.globl _KiServiceExit
-.globl _KiServiceExit2
-.globl _KiFastCallEntry
-.globl _KiSystemService
-.globl _KiDebugService
-.globl _Kei386EoiHelper@0
-.globl _NtRaiseException@12
-.globl _NtContinue@8
-.intel_syntax noprefix
-
-/*
- * FIXMEs:
- * - Figure out why ES/DS gets messed up in VMWare, when doing
KiServiceExit only,
- * and only when called from user-mode, and returning to
user-mode.
- * - Merge with trap.S and document all traps.
- * - Use MmProbe when copying arguments to syscall.
- * - Add DR macro/save and VM macro/save.
- * - Implement KiCallbackReturn, KiGetTickCount,
KiRaiseAssertion
- */
-
-/* FUNCTIONS
***************************************************************/
-
-.func KiSystemService
-_KiSystemService:
-
- /* Enter the shared system call prolog */
- SYSCALL_PROLOG
-
- /* Jump to the actual handler */
- jmp SharedCode
-.endfunc
-
-BadStack:
-
- /* Restore ESP0 stack */
- mov ecx, [fs:KPCR_TSS]
- mov esp, ss:[ecx+KTSS_ESP0]
-
- /* Generate V86M Stack for Trap 6 */
- push 0
- push 0
- push 0
- push 0
-
- /* Generate interrupt stack for Trap 6 */
- push KGDT_R3_DATA + RPL_MASK
- push 0
- push 0x20202
- push KGDT_R3_CODE + RPL_MASK
- push 0
- jmp _KiTrap6
-
-.func KiFastCallEntry
-_KiFastCallEntry:
-
- /* Set FS to PCR */
- mov ecx, KGDT_R0_PCR
- mov fs, cx
-
- /* Set DS/ES to Kernel Selector */
- mov ecx, KGDT_R0_DATA
- mov ds, cx
- mov es, cx
-
- /* Set the current stack to Kernel Stack */
- mov ecx, [fs:KPCR_TSS]
- mov esp, ss:[ecx+KTSS_ESP0]
-
- /* Set up a fake INT Stack. */
- push KGDT_R3_DATA + RPL_MASK
- 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], EFLAGS_INTERRUPT_MASK /* Re-enable IRQs in
EFLAGS, to fake INT */
- push KGDT_R3_CODE + RPL_MASK
- push KUSER_SHARED_SYSCALL_RET
-
- /* Setup the Trap Frame stack */
- push 0
- push ebp
- push ebx
- push esi
- push edi
- push KGDT_R3_TEB + RPL_MASK
-
- /* Save pointer to our PCR */
- mov ebx, [fs:KPCR_SELF]
-
- /* Get a pointer to the current thread */
- mov esi, [ebx+KPCR_CURRENT_THREAD]
-
- /* Set the exception handler chain terminator */
- push [ebx+KPCR_EXCEPTION_LIST]
- mov dword ptr [ebx+KPCR_EXCEPTION_LIST], -1
-
- /* Use the thread's stack */
- mov ebp, [esi+KTHREAD_INITIAL_STACK]
-
- /* Push previous mode */
- push UserMode
-
- /* Skip the other registers */
- sub esp, 0x48
-
- /* Hack: it seems that on VMWare someone damages ES/DS on exit.
Investigate! */
- mov dword ptr [esp+KTRAP_FRAME_DS], KGDT_R3_DATA + RPL_MASK
- mov dword ptr [esp+KTRAP_FRAME_ES], KGDT_R3_DATA + RPL_MASK
-
- /* Make space for us on the stack */
- sub ebp, 0x29C
-
- /* Write the previous mode */
- mov byte ptr [esi+KTHREAD_PREVIOUS_MODE], UserMode
-
- /* Sanity check */
- cmp ebp, esp
- jnz BadStack
-
- /* Flush DR7 */
- and dword ptr [ebp+KTRAP_FRAME_DR7], 0
-
- /* Check if the thread was being debugged */
- test byte ptr [esi+KTHREAD_DEBUG_ACTIVE], 0xFF
-
- /* Set the thread's trap frame */
- mov [esi+KTHREAD_TRAP_FRAME], ebp
-
- /* Save DR registers if needed */
- //jnz Dr_FastCallDrSave
-
- /* Set the trap frame debug header */
- SET_TF_DEBUG_HEADER
-
-#ifdef DBG // FIXME: Is this for GDB? Can it be moved in the stub?
- /*
- * We want to know the address from where the syscall stub was
called.
- * If PrevMode is KernelMode, that address is stored in our own
(kernel)
- * stack, at location KTRAP_FRAME_ESP.
- * If we're coming from UserMode, we load the usermode stack
pointer
- * and go back two frames (first frame is the syscall stub, second
call
- * is the caller of the stub).
- */
- mov edi, [ebp+KTRAP_FRAME_ESP]
- test byte ptr [esi+KTHREAD_PREVIOUS_MODE], 0x01
- jz PrevWasKernelMode
- mov edi, [edi+4]
-PrevWasKernelMode:
- mov [ebp+KTRAP_FRAME_DEBUGEIP], edi
-#endif
-
- /* Enable interrupts */
- sti
-
-SharedCode:
-
- /*
- * Find out which table offset to use. Converts 0x1124 into 0x10.
- * The offset is related to the Table Index as such: Offset =
TableIndex x 10
- */
- mov edi, eax
- shr edi, SERVICE_TABLE_SHIFT
- and edi, SERVICE_TABLE_MASK
- mov ecx, edi
-
- /* Now add the thread's base system table to the offset */
- add edi, [esi+KTHREAD_SERVICE_TABLE]
-
- /* Get the true syscall ID and check it */
- mov ebx, eax
- and eax, SERVICE_NUMBER_MASK
- cmp eax, [edi+SERVICE_DESCRIPTOR_LIMIT]
-
- /* Invalid ID, try to load Win32K Table */
- jnb KiBBTUnexpectedRange
-
-#if 0 // <== Disabled for two reasons: We don't save TEB in 0x18, but
KPCR.
- // <== We don't have a KeGdiFlushUserBatch callback yet (needs to
be
- // sent through the PsInitializeWin32Callouts structure)
- /* Check if this was Win32K */
- cmp ecx, SERVICE_TABLE_TEST
- jnz NotWin32K
-
- /* Get the TEB */
- mov ecx, [fs:KPCR_TEB]
-
- /* Check if we should flush the User Batch */
- xor ebx, ebx
- or ebx, [ecx+TEB_GDI_BATCH_COUNT]
- jz NoWin32K
-
- /* Flush it */
- push edx
- push eax
- call [_KeGdiFlushUserBatch]
- pop eax
- pop edx
-#endif
-
-NotWin32K:
- /* Increase total syscall count */
- inc dword ptr fs:[KPCR_SYSTEM_CALLS]
-
-#ifdef DBG
- /* Increase per-syscall count */
- mov ecx, [edi+SERVICE_DESCRIPTOR_COUNT]
- jecxz NoCountTable
- inc dword ptr [ecx+eax*4]
-#endif
-
- /* Users's current stack frame pointer is source */
-NoCountTable:
- mov esi, edx
-
- /* Allocate room for argument list from kernel stack */
- mov ebx, [edi+SERVICE_DESCRIPTOR_NUMBER]
- xor ecx, ecx
- mov cl, [eax+ebx]
-
- /* Get pointer to function */
- mov edi, [edi+SERVICE_DESCRIPTOR_BASE]
- mov ebx, [edi+eax*4]
-
- /* Allocate space on our stack */
- sub esp, ecx
-
- /*
- * Copy the arguments from the user stack to our stack
- * FIXME: This needs to be probed with MmSystemRangeStart
- */
- shr ecx, 2
- mov edi, esp
- rep movsd
-
-#ifdef DBG
-
- /* Make sure this isn't a user-mode call at elevated IRQL */
- test byte ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
- jz SkipCheck
- call _KeGetCurrentIrql@0
- or al, al
- jnz InvalidIrql
-
- /*
- * The following lines are for the benefit of GDB. It will see the
return
- * address of the "call ebx" below, find the last label before it
and
- * thinks that that's the start of the function. It will then check
to see
- * if it starts with a standard function prolog (push ebp, mov
ebp,esp).
- * When that standard function prolog is not found, it will stop
the
- * stack backtrace. Since we do want to backtrace into usermode,
let's
- * make GDB happy and create a standard prolog.
- */
-SkipCheck:
-KiSystemService:
- push ebp
- mov ebp,esp
- pop ebp
-#endif
-
- /* Do the System Call */
- call ebx
-
-#ifdef DBG
- /* Make sure the user-mode call didn't return at elevated IRQL */
- test byte ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
- jz SkipCheck2
- mov esi, eax /* We need to save the syscall's return
val */
- call _KeGetCurrentIrql@0
- or al, al
- jnz InvalidIrql
- mov eax, esi /* Restore it */
-
- /* Get our temporary current thread pointer for sanity check */
- mov ecx, fs:[KPCR_CURRENT_THREAD]
-
- /* Make sure that we are not attached and that APCs are not
disabled */
- mov dl, [ecx+KTHREAD_APC_STATE_INDEX]
- or dl, dl
- jnz InvalidIndex
- mov edx, [ecx+KTHREAD_COMBINED_APC_DISABLE]
- or edx, edx
- jnz InvalidIndex
-#endif
-
-SkipCheck2:
-
- /* Deallocate the kernel stack frame */
- mov esp, ebp
-
-KeReturnFromSystemCall:
-
- /* Get the Current Thread */
- mov ecx, [fs:KPCR_CURRENT_THREAD]
-
- /* Restore the old trap frame pointer */
- mov edx, [ebp+KTRAP_FRAME_EDX]
- mov [ecx+KTHREAD_TRAP_FRAME], edx
-.endfunc
-
-.func KiServiceExit
-_KiServiceExit:
- /* Disable interrupts */
- cli
-
- /* Check for, and deliver, User-Mode APCs if needed */
- CHECK_FOR_APC_DELIVER 1
-
- /* Hack for VMWare: Sometimes ES/DS seem to be invalid when
returning to user-mode. Investigate! */
- mov es, [ebp+KTRAP_FRAME_ES]
- mov ds, [ebp+KTRAP_FRAME_DS]
-
- /* Exit and cleanup */
- TRAP_EPILOG FromSystemCall, DoRestorePreviousMode,
DoNotRestoreSegments, DoNotRestoreVolatiles, DoRestoreEverything
-.endfunc
-
-KiBBTUnexpectedRange:
-
- /* If this isn't a Win32K call, fail */
- cmp ecx, 0x10
- jne InvalidCall
-
- /* Set up Win32K Table */
- push edx
- push ebx
- call _PsConvertToGuiThread@0
-
- /* FIXME: Handle failure */
- pop eax
- pop edx
-
- /* Reset trap frame address */
- mov ebp, esp
- mov [esi+KTHREAD_TRAP_FRAME], ebp
-
- /* Try the Call again */
- jmp SharedCode
-
-InvalidCall:
-
- /* Invalid System Call */
- mov eax, STATUS_INVALID_SYSTEM_SERVICE
- jmp KeReturnFromSystemCall
-
-#ifdef DBG
-InvalidIrql:
- /* Save current IRQL */
- push fs:[KPCR_IRQL]
-
- /* Set us at passive */
- mov dword ptr fs:[KPCR_IRQL], 0
- cli
-
- /* Bugcheck */
- push 0
- push 0
- push eax
- push ebx
- push IRQL_GT_ZERO_AT_SYSTEM_SERVICE
- call _KeBugCheckEx@20
-
-InvalidIndex:
-
- /* Get the index and APC state */
- movzx eax, byte ptr [ecx+KTHREAD_APC_STATE_INDEX]
- mov edx, [ecx+KTHREAD_COMBINED_APC_DISABLE]
-
- /* Bugcheck */
- push 0
- push edx
- push eax
- push ebx
- push APC_INDEX_MISMATCH
- call _KeBugCheckEx@20
- ret
-#endif
-
-.func KiServiceExit2
-_KiServiceExit2:
-
- /* Disable interrupts */
- cli
-
- /* Check for, and deliver, User-Mode APCs if needed */
- CHECK_FOR_APC_DELIVER 0
-
- /* Exit and cleanup */
- TRAP_EPILOG NotFromSystemCall, DoRestorePreviousMode,
DoRestoreSegments, DoRestoreVolatiles, DoNotRestoreEverything
-.endfunc
-
-.func Kei386EoiHelper@0
-_Kei386EoiHelper@0:
-
- /* Disable interrupts */
- cli
-
- /* Check for, and deliver, User-Mode APCs if needed */
- CHECK_FOR_APC_DELIVER 0
-
- /* Exit and cleanup */
- TRAP_EPILOG NotFromSystemCall, DoNotRestorePreviousMode,
DoRestoreSegments, DoRestoreVolatiles, DoNotRestoreEverything
-.endfunc
-
-V86_Exit:
- /* Move to EDX position */
- add esp, KTRAP_FRAME_EDX
-
- /* Restore volatiles */
- pop edx
- pop ecx
- pop eax
-
- /* Move to non-volatiles */
- lea esp, [ebp+KTRAP_FRAME_EDI]
- pop edi
- pop esi
- pop ebx
- pop ebp
-
- /* Skip error code and return */
- add esp, 4
- iret
-
-AbiosExit:
- /* Not yet supported */
- int 3
-
-_KiDebugService:
-
- /* Push error code */
- push 0
-
- /* Enter trap */
- TRAP_PROLOG(kids)
-
- /* Increase EIP so we skip the INT3 */
- //inc dword ptr [ebp+KTRAP_FRAME_EIP]
-
- /* Call debug service dispatcher */
- mov eax, [ebp+KTRAP_FRAME_EAX]
- mov ecx, [ebp+KTRAP_FRAME_ECX]
- mov edx, [ebp+KTRAP_FRAME_EAX]
-
- /* Check for V86 mode */
- test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
- jnz NotUserMode
-
- /* Check if this is kernel or user-mode */
- test byte ptr [ebp+KTRAP_FRAME_CS], 1
- jz CallDispatch
- cmp word ptr [ebp+KTRAP_FRAME_CS], KGDT_R3_CODE + RPL_MASK
- jnz NotUserMode
-
- /* Re-enable interrupts */
-VdmProc:
- sti
-
- /* Call the debug routine */
-CallDispatch:
- mov esi, ecx
- mov edi, edx
- mov edx, eax
- mov ecx, 3
- push edi
- push esi
- push edx
- call _KdpServiceDispatcher@12
-
-NotUserMode:
-
- /* Get the current process */
- mov ebx, [fs:KPCR_CURRENT_THREAD]
- mov ebx, [ebx+KTHREAD_APCSTATE_PROCESS]
-
- /* Check if this is a VDM Process */
- //cmp dword ptr [ebx+KPROCESS_VDM_OBJECTS], 0
- //jz VdmProc
-
- /* Exit through common routine */
- jmp _Kei386EoiHelper@0
-
-_NtRaiseException@12:
-
- /* NOTE: We -must- be called by Zw* to have the right frame! */
- /* Push the stack frame */
- push ebp
-
- /* Get the current thread and restore its trap frame */
- mov ebx, [fs:KPCR_CURRENT_THREAD]
- mov edx, [ebp+KTRAP_FRAME_EDX]
- mov [ebx+KTHREAD_TRAP_FRAME], edx
-
- /* Set up stack frame */
- mov ebp, esp
-
- /* Get the Trap Frame in EBX */
- mov ebx, [ebp+0]
-
- /* Get the exception list and restore */
- mov eax, [ebx+KTRAP_FRAME_EXCEPTION_LIST]
- mov [fs:KPCR_EXCEPTION_LIST], eax
-
- /* Get the parameters */
- mov edx, [ebp+16] /* Search frames */
- mov ecx, [ebp+12] /* Context */
- mov eax, [ebp+8] /* Exception Record */
-
- /* Raise the exception */
- push edx
- push ebx
- push 0
- push ecx
- push eax
- call _KiRaiseException@20
-
- /* Restore trap frame in EBP */
- pop ebp
- mov esp, ebp
-
- /* Check the result */
- or eax, eax
- jz _KiServiceExit2
-
- /* Restore debug registers too */
- jmp _KiServiceExit
-
-_NtContinue@8:
-
- /* NOTE: We -must- be called by Zw* to have the right frame! */
- /* Push the stack frame */
- push ebp
-
- /* Get the current thread and restore its trap frame */
- mov ebx, [fs:KPCR_CURRENT_THREAD]
- mov edx, [ebp+KTRAP_FRAME_EDX]
- mov [ebx+KTHREAD_TRAP_FRAME], edx
-
- /* Set up stack frame */
- mov ebp, esp
-
- /* Save the parameters */
- mov eax, [ebp+0]
- mov ecx, [ebp+8]
-
- /* Call KiContinue */
- push eax
- push 0
- push ecx
- call _KiContinue@12
-
- /* Check if we failed (bad context record) */
- or eax, eax
- jnz Error
-
- /* Check if test alert was requested */
- cmp dword ptr [ebp+12], 0
- je DontTest
-
- /* Test alert for the thread */
- mov al, [ebx+KTHREAD_PREVIOUS_MODE]
- push eax
- call _KeTestAlertThread@4
-
-DontTest:
- /* Return to previous context */
- pop ebp
- mov esp, ebp
- jmp _KiServiceExit2
-
-Error:
- pop ebp
- mov esp, ebp
- jmp _KiServiceExit
-
_____
Modified: trunk/reactos/ntoskrnl/ke/i386/trap.s
--- trunk/reactos/ntoskrnl/ke/i386/trap.s 2006-01-17 05:54:35 UTC
(rev 20935)
+++ trunk/reactos/ntoskrnl/ke/i386/trap.s 2006-01-17 06:36:35 UTC
(rev 20936)
@@ -1,31 +1,625 @@
/*
- * PROJECT: ReactOS kernel
- * FILE: ntoskrnl/ke/i386/trap.s
- * PURPOSE: Exception handlers
- * PROGRAMMERS: Alex Ionescu (alex(a)relsoft.net)
+ * FILE: ntoskrnl/ke/i386/trap.S
+ * COPYRIGHT: See COPYING in the top level directory
+ * PURPOSE: System Traps, Entrypoints and Exitpoints
+ * PROGRAMMER: Alex Ionescu (alex(a)relsoft.net)
+ * NOTE: See asmmacro.S for the shared entry/exit code.
*/
/* INCLUDES
******************************************************************/
#include <asm.h>
#include <internal/i386/asmmacro.S>
+.intel_syntax noprefix
-/* NOTES:
- * Why not share the epilogue?
- * 1) An extra jmp is expensive (jmps are very costly)
- * 2) Eventually V86 exit should be handled through ABIOS, and we
- * handle ABIOS exit in the shared trap exit code already.
- * Why not share the KiTrapHandler call?
- * 1) Would make using the trap-prolog macro much harder.
- * 2) Eventually some of these traps might be re-implemented in
assembly
- * to improve speed and depend less on the compiler and/or use
features
- * not present as C keywords. When that happens, less traps will use
the
- * shared C handler, so the shared-code would need to be un-shared.
- */
+/*
+ * FIXMEs:
+ * - Figure out why ES/DS gets messed up in VMWare, when doing
KiServiceExit only,
+ * and only when called from user-mode, and returning to
user-mode.
+ * - Use MmProbe when copying arguments to syscall.
+ * - Handle failure after PsConvertToGuiThread.
+ * - Figure out what the DEBUGEIP hack is for and how it can
be moved away.
+ * - Add DR macro/save and VM macro/save.
+ * - Add .func .endfunc to everything that doesn't have it
yet.
+ * - Implement KiCallbackReturn, KiGetTickCount,
KiRaiseAssertion.
+ */
-/* FUNCTIONS
*****************************************************************/
+/* GLOBALS
******************************************************************/
-.globl _KiTrap0
+/* This is the Software Interrupt Table that we handle in this file:
*/
+.globl _KiTrap0 /* INT 0: Divide Error (#DE)
*/
+.globl _KiTrap1 /* INT 1: Debug Exception (#DB)
*/
+.globl _KiTrap2 /* INT 2: NMI Interrupt
*/
+.globl _KiTrap3 /* INT 3: Breakpoint Exception
(#BP) */
+.globl _KiTrap4 /* INT 4: Overflow Exception (#OF)
*/
+.globl _KiTrap5 /* INT 5: BOUND Range Exceeded
(#BR) */
+.globl _KiTrap6 /* INT 6: Invalid Opcode Code (#UD)
*/
+.globl _KiTrap7 /* INT 7: Device Not Available
(#NM) */
+.globl _KiTrap8 /* INT 8: Double Fault Exception
(#DF) */
+.globl _KiTrap9 /* INT 9: RESERVED
*/
+.globl _KiTrap10 /* INT 10: Invalid TSS Exception
(#TS) */
+.globl _KiTrap11 /* INT 11: Segment Not Present
(#NP) */
+.globl _KiTrap12 /* INT 12: Stack Fault Exception
(#SS) */
+.globl _KiTrap13 /* INT 13: General Protection (#GP)
*/
+.globl _KiTrap14 /* INT 14: Page-Fault Exception
(#PF) */
+.globl _KiTrap15 /* INT 15: RESERVED
*/
+.globl _KiTrap16 /* INT 16: x87 FPU Error (#MF)
*/
+.globl _KiTrap17 /* INT 17: Align Check Exception
(#AC) */
+.globl _KiTrap18 /* INT 18: Machine Check Exception
(#MC)*/
+.globl _KiTrap19 /* INT 19: SIMD FPU Exception (#XF)
*/
+.globl _KiTrapUnknown /* INT 20-30: UNDEFINED INTERRUPTS
*/
+.globl _KiDebugService /* INT 31: Get Tick Count Handler
*/
+.globl _KiCallbackReturn /* INT 32: User-Mode Callback
Return */
+.globl _KiRaiseAssertion /* INT 33: Debug Assertion Handler
*/
+.globl _KiDebugService /* INT 34: Debug Service Handler
*/
+.globl _KiSystemService /* INT 35: System Call Service
Handler */
+
+/* We also handle LSTAR Entry
*/
+.globl _KiFastCallEntry
+
+/* And special system-defined software traps
*/
+.globl _NtRaiseException@12
+.globl _NtContinue@8
+
+/* We implement the following trap exit points:
*/
+.globl _KiServiceExit /* Exit from syscall
*/
+.globl _KiServiceExit2 /* Exit from syscall with complete
frame*/
+.globl _Kei386EoiHelper@0 /* Exit from interrupt or H/W trap
*/
+
+/* FUNCTIONS
****************************************************************/
+
+.func KiSystemService
+_KiSystemService:
+
+ /* Enter the shared system call prolog */
+ SYSCALL_PROLOG
+
+ /* Jump to the actual handler */
+ jmp SharedCode
+.endfunc
+
+.func KiFastCallEntry
+_KiFastCallEntry:
+
+ /* Set FS to PCR */
+ mov ecx, KGDT_R0_PCR
+ mov fs, cx
+
+ /* Set DS/ES to Kernel Selector */
+ mov ecx, KGDT_R0_DATA
+ mov ds, cx
+ mov es, cx
+
+ /* Set the current stack to Kernel Stack */
+ mov ecx, [fs:KPCR_TSS]
+ mov esp, ss:[ecx+KTSS_ESP0]
+
+ /* Set up a fake INT Stack. */
+ push KGDT_R3_DATA + RPL_MASK
+ 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], EFLAGS_INTERRUPT_MASK /* Re-enable IRQs in
EFLAGS, to fake INT */
+ push KGDT_R3_CODE + RPL_MASK
+ push KUSER_SHARED_SYSCALL_RET
+
+ /* Setup the Trap Frame stack */
+ push 0
+ push ebp
+ push ebx
+ push esi
+ push edi
+ push KGDT_R3_TEB + RPL_MASK
+
+ /* Save pointer to our PCR */
+ mov ebx, [fs:KPCR_SELF]
+
+ /* Get a pointer to the current thread */
+ mov esi, [ebx+KPCR_CURRENT_THREAD]
+
+ /* Set the exception handler chain terminator */
+ push [ebx+KPCR_EXCEPTION_LIST]
+ mov dword ptr [ebx+KPCR_EXCEPTION_LIST], -1
+
+ /* Use the thread's stack */
+ mov ebp, [esi+KTHREAD_INITIAL_STACK]
+
+ /* Push previous mode */
+ push UserMode
+
+ /* Skip the other registers */
+ sub esp, 0x48
+
+ /* Hack: it seems that on VMWare someone damages ES/DS on exit.
Investigate! */
+ mov dword ptr [esp+KTRAP_FRAME_DS], KGDT_R3_DATA + RPL_MASK
+ mov dword ptr [esp+KTRAP_FRAME_ES], KGDT_R3_DATA + RPL_MASK
+
+ /* Make space for us on the stack */
+ sub ebp, 0x29C
+
+ /* Write the previous mode */
+ mov byte ptr [esi+KTHREAD_PREVIOUS_MODE], UserMode
+
+ /* Sanity check */
+ cmp ebp, esp
+ jnz BadStack
+
+ /* Flush DR7 */
+ and dword ptr [ebp+KTRAP_FRAME_DR7], 0
+
+ /* Check if the thread was being debugged */
+ test byte ptr [esi+KTHREAD_DEBUG_ACTIVE], 0xFF
+
+ /* Set the thread's trap frame */
+ mov [esi+KTHREAD_TRAP_FRAME], ebp
+
+ /* Save DR registers if needed */
+ //jnz Dr_FastCallDrSave
+
+ /* Set the trap frame debug header */
+ SET_TF_DEBUG_HEADER
+
+#ifdef DBG // FIXME: Is this for GDB? Can it be moved in the stub?
+ /*
+ * We want to know the address from where the syscall stub was
called.
+ * If PrevMode is KernelMode, that address is stored in our own
(kernel)
+ * stack, at location KTRAP_FRAME_ESP.
+ * If we're coming from UserMode, we load the usermode stack
pointer
+ * and go back two frames (first frame is the syscall stub, second
call
+ * is the caller of the stub).
+ */
+ mov edi, [ebp+KTRAP_FRAME_ESP]
+ test byte ptr [esi+KTHREAD_PREVIOUS_MODE], 0x01
+ jz PrevWasKernelMode
+ mov edi, [edi+4]
+PrevWasKernelMode:
+ mov [ebp+KTRAP_FRAME_DEBUGEIP], edi
+#endif
+
+ /* Enable interrupts */
+ sti
+
+SharedCode:
+
+ /*
+ * Find out which table offset to use. Converts 0x1124 into 0x10.
+ * The offset is related to the Table Index as such: Offset =
TableIndex x 10
+ */
+ mov edi, eax
+ shr edi, SERVICE_TABLE_SHIFT
+ and edi, SERVICE_TABLE_MASK
+ mov ecx, edi
+
+ /* Now add the thread's base system table to the offset */
+ add edi, [esi+KTHREAD_SERVICE_TABLE]
+
+ /* Get the true syscall ID and check it */
+ mov ebx, eax
+ and eax, SERVICE_NUMBER_MASK
+ cmp eax, [edi+SERVICE_DESCRIPTOR_LIMIT]
+
+ /* Invalid ID, try to load Win32K Table */
+ jnb KiBBTUnexpectedRange
+
+#if 0 // <== Disabled for two reasons: We don't save TEB in 0x18, but
KPCR.
+ // <== We don't have a KeGdiFlushUserBatch callback yet (needs to
be
+ // sent through the PsInitializeWin32Callouts structure)
+ /* Check if this was Win32K */
+ cmp ecx, SERVICE_TABLE_TEST
+ jnz NotWin32K
+
+ /* Get the TEB */
+ mov ecx, [fs:KPCR_TEB]
+
+ /* Check if we should flush the User Batch */
+ xor ebx, ebx
+ or ebx, [ecx+TEB_GDI_BATCH_COUNT]
+ jz NoWin32K
+
+ /* Flush it */
+ push edx
+ push eax
+ call [_KeGdiFlushUserBatch]
+ pop eax
+ pop edx
+#endif
+
+NotWin32K:
+ /* Increase total syscall count */
+ inc dword ptr fs:[KPCR_SYSTEM_CALLS]
+
+#ifdef DBG
+ /* Increase per-syscall count */
+ mov ecx, [edi+SERVICE_DESCRIPTOR_COUNT]
+ jecxz NoCountTable
+ inc dword ptr [ecx+eax*4]
+#endif
+
+ /* Users's current stack frame pointer is source */
+NoCountTable:
+ mov esi, edx
+
+ /* Allocate room for argument list from kernel stack */
+ mov ebx, [edi+SERVICE_DESCRIPTOR_NUMBER]
+ xor ecx, ecx
+ mov cl, [eax+ebx]
+
+ /* Get pointer to function */
+ mov edi, [edi+SERVICE_DESCRIPTOR_BASE]
+ mov ebx, [edi+eax*4]
+
+ /* Allocate space on our stack */
+ sub esp, ecx
+
+ /*
+ * Copy the arguments from the user stack to our stack
+ * FIXME: This needs to be probed with MmSystemRangeStart
+ */
+ shr ecx, 2
+ mov edi, esp
+ rep movsd
+
+#ifdef DBG
+
+ /* Make sure this isn't a user-mode call at elevated IRQL */
+ test byte ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
+ jz SkipCheck
+ call _KeGetCurrentIrql@0
+ or al, al
+ jnz InvalidIrql
+
+ /*
+ * The following lines are for the benefit of GDB. It will see the
return
+ * address of the "call ebx" below, find the last label before it
and
+ * thinks that that's the start of the function. It will then check
to see
+ * if it starts with a standard function prolog (push ebp, mov
ebp,esp).
+ * When that standard function prolog is not found, it will stop
the
+ * stack backtrace. Since we do want to backtrace into usermode,
let's
+ * make GDB happy and create a standard prolog.
+ */
+SkipCheck:
+KiSystemService:
+ push ebp
+ mov ebp,esp
+ pop ebp
+#endif
+
+ /* Do the System Call */
+ call ebx
+
+#ifdef DBG
+ /* Make sure the user-mode call didn't return at elevated IRQL */
+ test byte ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
+ jz SkipCheck2
+ mov esi, eax /* We need to save the syscall's return
val */
+ call _KeGetCurrentIrql@0
+ or al, al
+ jnz InvalidIrql
+ mov eax, esi /* Restore it */
+
+ /* Get our temporary current thread pointer for sanity check */
+ mov ecx, fs:[KPCR_CURRENT_THREAD]
+
+ /* Make sure that we are not attached and that APCs are not
disabled */
+ mov dl, [ecx+KTHREAD_APC_STATE_INDEX]
+ or dl, dl
+ jnz InvalidIndex
+ mov edx, [ecx+KTHREAD_COMBINED_APC_DISABLE]
+ or edx, edx
+ jnz InvalidIndex
+#endif
+
+SkipCheck2:
+
[truncated at 1000 lines; 538 more skipped]
- Implement SYSCALL_PROLOG for the main handler and the three
fast-system calls (ints 2b, 2c, 2d) which are not yet implemented.
- Document the macros.
Modified: trunk/reactos/ntoskrnl/include/internal/i386/asmmacro.S
Modified: trunk/reactos/ntoskrnl/ke/i386/syscall.S
_____
Modified: trunk/reactos/ntoskrnl/include/internal/i386/asmmacro.S
--- trunk/reactos/ntoskrnl/include/internal/i386/asmmacro.S
2006-01-17 05:22:00 UTC (rev 20934)
+++ trunk/reactos/ntoskrnl/include/internal/i386/asmmacro.S
2006-01-17 05:54:35 UTC (rev 20935)
@@ -234,16 +234,124 @@
SET_TF_DEBUG_HEADER
//
-// @name TRAP_EPILOG
+// @name SYSCALL_PROLOG
//
-// This macro creates a standard trap entry prologue.
-// It should be used for entry into any kernel trap (KiTrapXx), but not
for
-// system calls, which require special handling.
+// This macro creates a system call entry prologue.
+// It should be used for entry into any fast-system call
(KiGetTickCount,
+// KiCallbackReturn, KiRaiseAssertion) and the generic system call
handler
+// (KiSystemService)
//
// @param Label
-// Identifying name of the caller function; will be used to
append
-// to the name V86 and DR helper functions, which must already
exist.
+// Unique label identifying the name of the caller function;
will be
+// used to append to the name of the DR helper function, which
must
+// already exist.
//
+// @remark None.
+//
+.macro SYSCALL_PROLOG
+ /* Create a trap frame */
+ push 0
+ push ebp
+ push ebx
+ push esi
+ push edi
+ push fs
+
+ /* Load PCR Selector into fs */
+ mov ebx, KGDT_R0_PCR
+ mov fs, bx
+
+ /* Get a pointer to the current thread */
+ mov esi, [fs:KPCR_CURRENT_THREAD]
+
+ /* Save the previous exception list */
+ push [fs:KPCR_EXCEPTION_LIST]
+
+ /* Set the exception handler chain terminator */
+ mov dword ptr [fs:KPCR_EXCEPTION_LIST], -1
+
+ /* Save the old previous mode */
+ push ss:[esi+KTHREAD_PREVIOUS_MODE]
+
+ /* Skip the other registers */
+ sub esp, 0x48
+
+ /* Hack: it seems that on VMWare someone damages ES/DS on exit.
Investigate! */
+ mov [esp+KTRAP_FRAME_DS], ds
+ mov [esp+KTRAP_FRAME_ES], es
+
+ /* Set the new previous mode based on the saved CS selector */
+ mov ebx, [esp+0x6C]
+ and ebx, 1
+ mov byte ptr ss:[esi+KTHREAD_PREVIOUS_MODE], bl
+
+ /* Go on the Kernel stack frame */
+ mov ebp, esp
+
+ /* Save the old trap frame pointer where EDX would be saved */
+ mov ebx, [esi+KTHREAD_TRAP_FRAME]
+ mov [ebp+KTRAP_FRAME_EDX], ebx
+
+ /* Flush DR7 */
+ and dword ptr [ebp+KTRAP_FRAME_DR7], 0
+
+ /* Check if the thread was being debugged */
+ test byte ptr [esi+KTHREAD_DEBUG_ACTIVE], 0xFF
+
+ /* Set the thread's trap frame and clear direction flag */
+ mov [esi+KTHREAD_TRAP_FRAME], ebp
+ cld
+
+ /* Save DR registers if needed */
+ //jnz Dr_kss_&Label
+
+ /* Set the trap frame debug header */
+ SET_TF_DEBUG_HEADER
+
+#ifdef DBG // FIXME: Is this for GDB? Can it be moved in the stub?
+ /*
+ * We want to know the address from where the syscall stub was
called.
+ * If PrevMode is KernelMode, that address is stored in our own
(kernel)
+ * stack, at location KTRAP_FRAME_ESP.
+ * If we're coming from UserMode, we load the usermode stack
pointer
+ * and go back two frames (first frame is the syscall stub, second
call
+ * is the caller of the stub).
+ */
+ mov edi, [ebp+KTRAP_FRAME_ESP]
+ test byte ptr [esi+KTHREAD_PREVIOUS_MODE], 0x01
+ jz 0f
+ mov edi, [edi+4]
+0:
+ mov [ebp+KTRAP_FRAME_DEBUGEIP], edi
+#endif
+
+ /* Enable interrupts */
+ sti
+.endm
+
+//
+// @name TRAP_EPILOG
+//
+// This macro creates an epilogue for leaving any system trap.
+// It is used for exiting system calls, exceptions, interrupts and
generic
+// traps.
+//
+// @param SystemCall
+// Specifies whether this trap will exit a system call. If so,
special
+// code will be assembled to potentially use SYSEXIT instead of
IRETD.
+//
+// @param RestorePreviousMode
+// Specifies if the previous mode should be restored.
+//
+// @param RestoreSegments
+// Specifies if the segment registers should be restored.
+//
+// @param RestoreVolatiles
+// Specifies if the volatile registers should be restored.
+//
+// @param RestoreAllRegs
+// Specifies if volatiles and segments should both be restored.
+//
// @remark
//
.macro TRAP_EPILOG SystemCall, RestorePreviousMode, RestoreSegments,
RestoreVolatiles, RestoreAllRegs
_____
Modified: trunk/reactos/ntoskrnl/ke/i386/syscall.S
--- trunk/reactos/ntoskrnl/ke/i386/syscall.S 2006-01-17 05:22:00 UTC
(rev 20934)
+++ trunk/reactos/ntoskrnl/ke/i386/syscall.S 2006-01-17 05:54:35 UTC
(rev 20935)
@@ -13,22 +13,33 @@
.globl _KiFastCallEntry
.globl _KiSystemService
.globl _KiDebugService
+.globl _Kei386EoiHelper@0
+.globl _NtRaiseException@12
+.globl _NtContinue@8
.intel_syntax noprefix
/*
* FIXMEs:
* - Figure out why ES/DS gets messed up in VMWare, when doing
KiServiceExit only,
* and only when called from user-mode, and returning to
user-mode.
- * - Implement SYSCALL_PROLOG macro.
+ * - Merge with trap.S and document all traps.
+ * - Use MmProbe when copying arguments to syscall.
+ * - Add DR macro/save and VM macro/save.
+ * - Implement KiCallbackReturn, KiGetTickCount,
KiRaiseAssertion
*/
- /*** This file is a mess; it is being worked on. Please contact Alex:
- *** alex(a)relsoft.net if you want to make any changes to it before
this
- *** message goes away
- */
-
/* FUNCTIONS
***************************************************************/
+.func KiSystemService
+_KiSystemService:
+
+ /* Enter the shared system call prolog */
+ SYSCALL_PROLOG
+
+ /* Jump to the actual handler */
+ jmp SharedCode
+.endfunc
+
BadStack:
/* Restore ESP0 stack */
@@ -123,68 +134,12 @@
/* Check if the thread was being debugged */
test byte ptr [esi+KTHREAD_DEBUG_ACTIVE], 0xFF
- /* Jump to shared code or DR Save */
- //jnz Dr_FastCallDrSave
- jmp SharedCode
-.endfunc
-
-.func KiSystemService
-_KiSystemService:
-
-// ==================== COMMON SYSTEM CALL CODE ============//
- /* Create a trap frame */
- push 0
- push ebp
- push ebx
- push esi
- push edi
- push fs
-
- /* Load PCR Selector into fs */
- mov ebx, KGDT_R0_PCR
- mov fs, bx
-
- /* Get a pointer to the current thread */
- mov esi, [fs:KPCR_CURRENT_THREAD]
-
- /* Save the previous exception list */
- push [fs:KPCR_EXCEPTION_LIST]
-
- /* Set the exception handler chain terminator */
- mov dword ptr [fs:KPCR_EXCEPTION_LIST], -1
-
- /* Save the old previous mode */
- push ss:[esi+KTHREAD_PREVIOUS_MODE]
-
- /* Skip the other registers */
- sub esp, 0x48
-
- /* Hack: it seems that on VMWare someone damages ES/DS on exit.
Investigate! */
- mov [esp+KTRAP_FRAME_DS], ds
- mov [esp+KTRAP_FRAME_ES], es
-
- /* Set the new previous mode based on the saved CS selector */
- mov ebx, [esp+0x6C]
- and ebx, 1
- mov byte ptr ss:[esi+KTHREAD_PREVIOUS_MODE], bl
-
- /* Go on the Kernel stack frame */
- mov ebp, esp
-
- /* Save the old trap frame pointer where EDX would be saved */
- mov ebx, [esi+KTHREAD_TRAP_FRAME]
- mov [ebp+KTRAP_FRAME_EDX], ebx
-
- /* Flush DR7 */
- and dword ptr [ebp+KTRAP_FRAME_DR7], 0
-
- /* Check if the thread was being debugged */
- test byte ptr [esi+KTHREAD_DEBUG_ACTIVE], 0xFF
- //jnz Dr_kss_a
-
-SharedCode:
+ /* Set the thread's trap frame */
mov [esi+KTHREAD_TRAP_FRAME], ebp
+ /* Save DR registers if needed */
+ //jnz Dr_FastCallDrSave
+
/* Set the trap frame debug header */
SET_TF_DEBUG_HEADER
@@ -208,7 +163,7 @@
/* Enable interrupts */
sti
-CheckValidCall:
+SharedCode:
/*
* Find out which table offset to use. Converts 0x1124 into 0x10.
@@ -389,14 +344,14 @@
mov [esi+KTHREAD_TRAP_FRAME], ebp
/* Try the Call again */
- jmp CheckValidCall
+ jmp SharedCode
InvalidCall:
/* Invalid System Call */
mov eax, STATUS_INVALID_SYSTEM_SERVICE
jmp KeReturnFromSystemCall
-
+
#ifdef DBG
InvalidIrql:
/* Save current IRQL */
@@ -443,7 +398,6 @@
TRAP_EPILOG NotFromSystemCall, DoRestorePreviousMode,
DoRestoreSegments, DoRestoreVolatiles, DoNotRestoreEverything
.endfunc
-.globl _Kei386EoiHelper@0
.func Kei386EoiHelper@0
_Kei386EoiHelper@0:
@@ -535,7 +489,6 @@
/* Exit through common routine */
jmp _Kei386EoiHelper@0
-.globl _NtRaiseException@12
_NtRaiseException@12:
/* NOTE: We -must- be called by Zw* to have the right frame! */
@@ -581,7 +534,6 @@
/* Restore debug registers too */
jmp _KiServiceExit
-.globl _NtContinue@8
_NtContinue@8:
/* NOTE: We -must- be called by Zw* to have the right frame! */