mirror of
https://github.com/reactos/reactos.git
synced 2024-07-06 04:35:07 +00:00
[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:
parent
425c57b083
commit
ee1da65d47
|
@ -846,4 +846,11 @@ Ki386PerfEnd(VOID)
|
|||
KeGetContextSwitches(KeGetCurrentPrcb()));
|
||||
}
|
||||
|
||||
FORCEINLINE
|
||||
PULONG
|
||||
KiGetUserModeStackAddress(void)
|
||||
{
|
||||
return &(KeGetCurrentThread()->TrapFrame->HardwareEsp);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue