- 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.

svn path=/trunk/; revision=20935
This commit is contained in:
Alex Ionescu 2006-01-17 05:54:35 +00:00
parent 087083224f
commit 93c504407b
2 changed files with 138 additions and 78 deletions

View file

@ -234,15 +234,123 @@
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
//

View file

@ -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.
*/
/*** 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
* - 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 */
@ -123,68 +134,12 @@ _KiFastCallEntry:
/* 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 @@ PrevWasKernelMode:
/* Enable interrupts */
sti
CheckValidCall:
SharedCode:
/*
* Find out which table offset to use. Converts 0x1124 into 0x10.
@ -389,14 +344,14 @@ KiBBTUnexpectedRange:
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 @@ _KiServiceExit2:
TRAP_EPILOG NotFromSystemCall, DoRestorePreviousMode, DoRestoreSegments, DoRestoreVolatiles, DoNotRestoreEverything
.endfunc
.globl _Kei386EoiHelper@0
.func Kei386EoiHelper@0
_Kei386EoiHelper@0:
@ -535,7 +489,6 @@ NotUserMode:
/* 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 @@ _NtRaiseException@12:
/* Restore debug registers too */
jmp _KiServiceExit
.globl _NtContinue@8
_NtContinue@8:
/* NOTE: We -must- be called by Zw* to have the right frame! */