[NTOSKRNL]

- Convert KiCallUserMode from asm to C (with a small asm wrapper)
- Convert KiGetUserModeStackAddress into a C inline function

svn path=/trunk/; revision=52855
This commit is contained in:
Timo Kreuzer 2011-07-25 00:01:29 +00:00
parent 425c57b083
commit ee1da65d47
5 changed files with 173 additions and 173 deletions

View file

@ -846,4 +846,11 @@ Ki386PerfEnd(VOID)
KeGetContextSwitches(KeGetCurrentPrcb()));
}
FORCEINLINE
PULONG
KiGetUserModeStackAddress(void)
{
return &(KeGetCurrentThread()->TrapFrame->HardwareEsp);
}
#endif

View file

@ -164,7 +164,7 @@ extern VOID __cdecl KiInterruptTemplate(VOID);
#define TIMER_WAIT_BLOCK 0x3L
#ifdef _M_ARM // FIXME: remove this once our headers are cleaned up
//
//
// A system call ID is formatted as such:
// .________________________________________________________________.
// | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
@ -187,7 +187,7 @@ extern VOID __cdecl KiInterruptTemplate(VOID);
//
// NB. From assembly code, the table number must be computed as an offset into
// the service descriptor table.
//
//
// Each entry into the table is 16 bytes long on 32-bit architectures, and
// 32 bytes long on 64-bit architectures.
//
@ -864,7 +864,7 @@ KeBugCheckWithTf(
ULONG_PTR BugCheckParameter4,
PKTRAP_FRAME Tf
);
BOOLEAN
NTAPI
KiHandleNmi(VOID);
@ -1020,12 +1020,6 @@ KiCallUserMode(
IN PULONG OutputLength
);
PULONG
NTAPI
KiGetUserModeStackAddress(
VOID
);
VOID
NTAPI
KiInitMachineDependent(VOID);

View file

@ -6,6 +6,7 @@
struct _EPROCESS;
extern PMMSUPPORT MmKernelAddressSpace;
extern PFN_NUMBER MiFreeSwapPages;
extern PFN_NUMBER MiUsedSwapPages;
extern SIZE_T MmTotalPagedPoolQuota;
@ -1134,7 +1135,7 @@ MiGetPfnEntry(IN PFN_NUMBER Pfn)
/* Make sure the PFN number is valid */
if (Pfn > MmHighestPhysicalPage) return NULL;
/* Make sure this page actually has a PFN entry */
if ((MiPfnBitMap.Buffer) && !(RtlTestBit(&MiPfnBitMap, (ULONG)Pfn))) return NULL;
@ -1338,7 +1339,7 @@ MmRawDeleteVirtualMapping(PVOID Address);
VOID
NTAPI
MmGetPageFileMapping(
struct _EPROCESS *Process,
struct _EPROCESS *Process,
PVOID Address,
SWAPENTRY* SwapEntry);
@ -1735,7 +1736,15 @@ MmCallDllInitialize(
IN PLIST_ENTRY ListHead
);
extern PMMSUPPORT MmKernelAddressSpace;
/* procsup.c *****************************************************************/
NTSTATUS
NTAPI
MmGrowKernelStack(
IN PVOID StackPointer
);
FORCEINLINE
VOID

View file

@ -208,4 +208,146 @@ KeUserModeCallback(IN ULONG RoutineIndex,
return CallbackStatus;
}
/* Stack layout:
*
* ----------------------------------
* KCALLOUT_FRAME.ResultLength <= 2nd Parameter to KiCallUserMode
* KCALLOUT_FRAME.Result <= 1st Parameter to KiCallUserMode
* KCALLOUT_FRAME.ReturnAddress <= Return address of KiCallUserMode
* KCALLOUT_FRAME.Ebp \
* KCALLOUT_FRAME.Ebx | = volatile registers, pushed
* KCALLOUT_FRAME.Esi | by KiCallUserMode
* KCALLOUT_FRAME.Edi /
* KCALLOUT_FRAME.CallbackStack
* KCALLOUT_FRAME.TrapFrame
* KCALLOUT_FRAME.InitialStack <= CalloutFrame points here
* ----------------------------------
* ~~ optional alignment ~~
* ----------------------------------
* FX_SAVE_AREA
* ----------------------------------
* KTRAP_FRAME
* ----------------------------------
* ~~ begin of stack frame for KiUserModeCallout ~~
*
*/
NTSTATUS
FASTCALL
KiUserModeCallout(PKCALLOUT_FRAME CalloutFrame)
{
PKTHREAD CurrentThread;
PKTRAP_FRAME TrapFrame, CallbackTrapFrame;
PFX_SAVE_AREA FxSaveArea, OldFxSaveArea;
PKPCR Pcr;
PKTSS Tss;
ULONG_PTR InitialStack;
NTSTATUS Status;
/* Get the current thread */
CurrentThread = KeGetCurrentThread();
#if DBG
/* Check if we are at pasive level */
if (KeGetCurrentIrql() != PASSIVE_LEVEL)
{
/* We're not, bugcheck */
KeBugCheckEx(IRQL_GT_ZERO_AT_SYSTEM_SERVICE,
0,
KeGetCurrentIrql(),
0,
0);
}
/* Check if we are attached or APCs are disabled */
if ((CurrentThread->ApcStateIndex != OriginalApcEnvironment) ||
(CurrentThread->CombinedApcDisable > 0))
{
KeBugCheckEx(APC_INDEX_MISMATCH,
0,
CurrentThread->ApcStateIndex,
CurrentThread->CombinedApcDisable,
0);
}
#endif
/* Align stack on 16-byte boundary */
InitialStack = (ULONG_PTR)CalloutFrame & ~15;
/* Check if we have enough space on the stack */
if ((InitialStack - KERNEL_STACK_SIZE) < CurrentThread->StackLimit)
{
/* We don't, we'll have to grow our stack */
Status = MmGrowKernelStack((PVOID)InitialStack);
/* Quit if we failed */
if (!NT_SUCCESS(Status)) return Status;
}
/* Save the current callback stack and initial stack */
CalloutFrame->CallbackStack = (ULONG_PTR)CurrentThread->CallbackStack;
CalloutFrame->InitialStack = (ULONG_PTR)CurrentThread->InitialStack;
/* Get and save the trap frame */
TrapFrame = CurrentThread->TrapFrame;
CalloutFrame->TrapFrame = (ULONG_PTR)TrapFrame;
/* Set the new callback stack */
CurrentThread->CallbackStack = CalloutFrame;
/* Set destination and origin NPX Areas */
OldFxSaveArea = (PVOID)(CalloutFrame->InitialStack - sizeof(FX_SAVE_AREA));
FxSaveArea = (PVOID)(InitialStack - sizeof(FX_SAVE_AREA));
/* Disable interrupts so we can fill the NPX State */
_disable();
/* Now copy the NPX State */
FxSaveArea->U.FnArea.ControlWord = OldFxSaveArea->U.FnArea.ControlWord;
FxSaveArea->U.FnArea.StatusWord = OldFxSaveArea->U.FnArea.StatusWord;
FxSaveArea->U.FnArea.TagWord = OldFxSaveArea->U.FnArea.TagWord;
FxSaveArea->U.FnArea.DataSelector = OldFxSaveArea->U.FnArea.DataSelector;
FxSaveArea->Cr0NpxState = OldFxSaveArea->Cr0NpxState;
/* Set the stack address */
CurrentThread->InitialStack = (PVOID)InitialStack;
/* Locate the trap frame on the callback stack */
CallbackTrapFrame = (PVOID)((ULONG_PTR)FxSaveArea - sizeof(KTRAP_FRAME));
/* Copy the trap frame to the new location */
*CallbackTrapFrame = *TrapFrame;
/* Get PCR */
Pcr = KeGetPcr();
/* Update the exception list */
CallbackTrapFrame->ExceptionList = Pcr->Used_ExceptionList;
/* Get TSS */
Tss = Pcr->TSS;
/* Bias the stack for V86 mode */
if (CallbackTrapFrame->EFlags & EFLAGS_V86_MASK)
{
/* Set new stack address in TSS */
Tss->Esp0 = (ULONG_PTR)(CallbackTrapFrame + 1);
}
else
{
/* Set new stack address in TSS */
Tss->Esp0 = (ULONG_PTR)&CallbackTrapFrame->V86Es;
}
/* Set user-mode dispatcher address as EIP */
CallbackTrapFrame->Eip = (ULONG_PTR)KeUserCallbackDispatcher;
/* Bring interrupts back */
_enable();
/* Exit to user-mode */
KiServiceExit(CallbackTrapFrame, 0);
}
/* EOF */

View file

@ -17,20 +17,11 @@ EXTERN _KeUserCallbackDispatcher:DWORD
EXTERN @KiServiceExit@8:PROC
EXTERN _KeGetCurrentIrql@0:PROC
EXTERN _KeBugCheckEx@20:PROC
EXTERN @KiUserModeCallout@4:PROC
/* FUNCTIONS ****************************************************************/
.code
PUBLIC _KiGetUserModeStackAddress@0
_KiGetUserModeStackAddress@0:
/* Get the current thread's trapframe and return the esp */
mov eax, fs:[KPCR_CURRENT_THREAD]
mov eax, [eax+KTHREAD_TRAP_FRAME]
lea eax, [eax+KTRAP_FRAME_ESP]
ret
/*++
* @name KiCallUserMode
*
@ -58,166 +49,23 @@ _KiGetUserModeStackAddress@0:
PUBLIC _KiCallUserMode@8
_KiCallUserMode@8:
/* Save volatile registers */
/* Push volatile registers on the stack.
This is part of the KCALLOUT_FRAME */
push ebp
push ebx
push esi
push edi
/* Get the current thread */
mov ebx, fs:[KPCR_CURRENT_THREAD]
/* load the address of the callout frame into ecx */
lea ecx, [esp - 12]
/* Make sure we're at passive */
#if DBG
call _KeGetCurrentIrql@0
or al, al
jz AtPassive
/* Allocate space for the inital stack */
sub esp, 12 + NPX_FRAME_LENGTH + KTRAP_FRAME_LENGTH + 16
/* We're not, bugcheck! */
push 0
push 0
push eax
push 0
push IRQL_GT_ZERO_AT_SYSTEM_SERVICE
call _KeBugCheckEx@20
call @KiUserModeCallout@4
AtPassive:
add esp, 12 + NPX_FRAME_LENGTH + KTRAP_FRAME_LENGTH + 16
/* Make sure that we are not attached and that APCs are not disabled */
movzx eax, byte ptr [ebx+KTHREAD_APC_STATE_INDEX]
mov edx, [ebx+KTHREAD_COMBINED_APC_DISABLE]
or eax, eax
jnz InvalidIndex
or edx, edx
jz ApcsEnabled
InvalidIndex:
push 0
push edx
push eax
push 0
push APC_INDEX_MISMATCH
call _KeBugCheckEx@20
ApcsEnabled:
#endif
/* Get the lowest stack limit and check if we can handle it */
lea eax, [esp-HEX(3000)]
cmp eax, [ebx+KTHREAD_STACK_LIMIT]
jnb StackOk
/* We can't, we'll have to grow our stack */
push esp
call _MmGrowKernelStack@4
/* Quit if we failed */
or eax, eax
jnz GrowFailed
/* Save the current callback stack */
StackOk:
push [ebx+KTHREAD_CALLBACK_STACK]
/* Get and save the trap frame */
mov edx, [ebx+KTHREAD_TRAP_FRAME]
push edx
/* Get and save the initial stack */
mov esi, [ebx+KTHREAD_INITIAL_STACK]
push esi
/* Set the new callback stack */
mov [ebx+KTHREAD_CALLBACK_STACK], esp
/* Align stack on 16-byte boundary */
and esp, NOT 15
mov edi, esp
/* Set destination and origin NPX Areas */
sub esp, NPX_FRAME_LENGTH
sub esi, NPX_FRAME_LENGTH
/* Disable interrupts so we can fill the NPX State */
cli
/* Now copy the NPX State */
mov ecx, [esi+FP_CONTROL_WORD]
mov [esp+FP_CONTROL_WORD], ecx
mov ecx, [esi+FP_STATUS_WORD]
mov [esp+FP_STATUS_WORD], ecx
mov ecx, [esi+FP_TAG_WORD]
mov [esp+FP_TAG_WORD], ecx
mov ecx, [esi+FP_DATA_SELECTOR]
mov [esp+FP_DATA_SELECTOR], ecx
mov ecx, [esi+FN_CR0_NPX_STATE]
mov [esp+FN_CR0_NPX_STATE], ecx
/* Get TSS */
mov esi, fs:[KPCR_TSS]
/* Set the stack address */
mov [ebx+KTHREAD_INITIAL_STACK], edi
/* Bias the stack for V86 mode */
mov ecx, esp
sub esp, 16
test dword ptr [edx+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
jnz DontBias
mov ecx, esp
DontBias:
/* Set new stack address in TSS */
mov [esi+KTSS_ESP0], ecx
/* Allocate the trap frame and set it */
sub esp, KTRAP_FRAME_V86_ES
mov ebp, esp
/* Set copy iterator and dest/origin parameters and do the copy */
mov ecx, (KTRAP_FRAME_V86_ES - KTRAP_FRAME_FS) / 4
lea edi, [esp+KTRAP_FRAME_FS]
lea esi, [edx+KTRAP_FRAME_FS]
rep movsd
/* Copy DR7 */
mov edi, [edx+KTRAP_FRAME_DR7]
test edi, NOT DR7_RESERVED_MASK
mov [esp+KTRAP_FRAME_DR7], edi
/* Check if we need to save debug registers */
jnz SaveDebug
/* Get user-mode dispatcher address and set it as EIP */
SetEip:
mov eax, dword ptr [_KeUserCallbackDispatcher]
mov [esp+KTRAP_FRAME_EIP], eax
/* Set the exception list */
mov eax, fs:[KPCR_EXCEPTION_LIST]
mov [esp+KTRAP_FRAME_EXCEPTION_LIST], eax
/* Set the previous mode */
mov eax, [edx+KTRAP_FRAME_PREVIOUS_MODE]
mov [esp+KTRAP_FRAME_PREVIOUS_MODE], eax
/* Bring interrupts back */
sti
/* Exit to user-mode */
mov ecx, esp
jmp @KiServiceExit@8
SaveDebug:
/* Copy all 5 DRs */
mov ecx, 5
lea edi, [esp+KTRAP_FRAME_DR0]
lea esi, [edx+KTRAP_FRAME_DR0]
rep movsd
jmp SetEip
GrowFailed:
/* Restore registers */
pop edi
pop esi