mirror of
https://github.com/reactos/reactos.git
synced 2024-11-11 01:04:11 +00:00
c424146e2c
svn path=/branches/cmake-bringup/; revision=48236
199 lines
4.8 KiB
ArmAsm
199 lines
4.8 KiB
ArmAsm
/*
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
* PROJECT: ReactOS kernel
|
|
* FILE: ntoskrnl/ke/amd64/ctxswitch.S
|
|
* PURPOSE: Thread Context Switching
|
|
*
|
|
* PROGRAMMER: Timo kreuzer (timo.kreuzer@reactos.org)
|
|
*/
|
|
|
|
/* INCLUDES ******************************************************************/
|
|
|
|
#include <reactos/asm.h>
|
|
#include <ndk/amd64/asm.h>
|
|
|
|
/* FUNCTIONS ****************************************************************/
|
|
|
|
.code64
|
|
|
|
/*++
|
|
* KiThreadStartup
|
|
*
|
|
* The KiThreadStartup routine is the beginning of any thread.
|
|
*
|
|
* Params:
|
|
* SystemRoutine - Pointer to the System Startup Routine. Either
|
|
* PspUserThreadStartup or PspSystemThreadStartup
|
|
*
|
|
* StartRoutine - For Kernel Threads only, specifies the starting execution
|
|
* point of the new thread.
|
|
*
|
|
* StartContext - For Kernel Threads only, specifies a pointer to variable
|
|
* context data to be sent to the StartRoutine above.
|
|
*
|
|
* UserThread - Indicates whether or not this is a user thread. This tells
|
|
* us if the thread has a context or not.
|
|
*
|
|
* TrapFrame - Pointer to the KTHREAD to which the caller wishes to
|
|
* switch from.
|
|
*
|
|
* Returns:
|
|
* Should never return for a system thread. Returns through the System Call
|
|
* Exit Dispatcher for a user thread.
|
|
*
|
|
* Remarks:
|
|
* If a return from a system thread is detected, a bug check will occur.
|
|
*
|
|
*--*/
|
|
PUBLIC KiThreadStartup
|
|
KiThreadStartup:
|
|
|
|
/*
|
|
* Clear all the non-volatile registers, so the thread won't be tempted to
|
|
* expect any static data (like some badly coded usermode/win9x apps do)
|
|
*/
|
|
xor rbx, rbx
|
|
xor rsi, rsi
|
|
xor rdi, rdi
|
|
xor rbp, rbp
|
|
xor r10, r10
|
|
xor r11, r11
|
|
xor r12, r12
|
|
xor r13, r13
|
|
xor r14, r14
|
|
xor r15, r15
|
|
|
|
/* It's now safe to go to APC */
|
|
mov rax, APC_LEVEL
|
|
mov cr8, rax
|
|
|
|
/*
|
|
* Call the System Routine which is right on our stack now.
|
|
* After we pop the pointer, the Start Routine/Context is on the
|
|
* stack, we pop it as parameters to the System Routine into rcx
|
|
*/
|
|
pop rax
|
|
pop rcx
|
|
call rax
|
|
|
|
/* The thread returned... was it a user-thread? */
|
|
pop rcx
|
|
or rcx, rcx
|
|
jz BadThread
|
|
|
|
/* Yes it was, set our trapframe for the System Call Exit Dispatcher */
|
|
mov ebp, esp
|
|
|
|
/* Exit back to user-mode */
|
|
// jmp _KiServiceExit2
|
|
UNIMPLEMENTED KiThreadStartup_KiServiceExit2
|
|
|
|
BadThread:
|
|
|
|
/* A system thread returned...this is very bad! */
|
|
int 3
|
|
|
|
|
|
/*++
|
|
* KiSwapContextInternal
|
|
*
|
|
* The KiSwapContextInternal routine switches context to another thread.
|
|
*
|
|
* Params:
|
|
* ESI - Pointer to the KTHREAD to which the caller wishes to
|
|
* switch to.
|
|
* EDI - Pointer to the KTHREAD to which the caller wishes to
|
|
* switch from.
|
|
*
|
|
* Returns:
|
|
* None.
|
|
*
|
|
* Remarks:
|
|
* Absolutely all registers except ESP can be trampled here for maximum code flexibility.
|
|
*
|
|
*--*/
|
|
PUBLIC KiSwapContextInternal
|
|
KiSwapContextInternal:
|
|
UNIMPLEMENTED KiSwapContextInternal
|
|
ret
|
|
|
|
|
|
/**
|
|
* KiSwapContext
|
|
*
|
|
* \brief
|
|
* The KiSwapContext routine switches context to another thread.
|
|
*
|
|
* BOOLEAN
|
|
* KiSwapContext(PKTHREAD CurrentThread, PKTHREAD TargetThread);
|
|
*
|
|
* \param CurrentThread
|
|
* Pointer to the KTHREAD of the current thread.
|
|
*
|
|
* \param TargetThread
|
|
* Pointer to the KTHREAD to which the caller wishes to switch to.
|
|
*
|
|
* \returns
|
|
* The WaitStatus of the Target Thread.
|
|
*
|
|
* \remarks
|
|
* This is a wrapper around KiSwapContextInternal which will save all the
|
|
* non-volatile registers so that the Internal function can use all of
|
|
* them. It will also save the old current thread and set the new one.
|
|
*
|
|
* The calling thread does not return after KiSwapContextInternal until
|
|
* another thread switches to IT.
|
|
*
|
|
*--*/
|
|
PUBLIC KiSwapContext
|
|
KiSwapContext:
|
|
|
|
/* Save 10 registers */
|
|
sub rsp, 10 * 8
|
|
|
|
/* Save all the non-volatile ones */
|
|
mov [rsp+72], r15
|
|
mov [rsp+64], r14
|
|
mov [rsp+56], r13
|
|
mov [rsp+48], r12
|
|
mov [rsp+40], r11
|
|
mov [rsp+32], r10
|
|
|
|
mov [rsp+24], rbx
|
|
mov [rsp+16], rsi
|
|
mov [rsp+8], rdi
|
|
mov [rsp+0], rbp
|
|
|
|
/* Get the PCR */
|
|
mov rbx, gs:[KPCR_SELF]
|
|
|
|
/* Get the current thread */
|
|
mov rdi, rcx
|
|
|
|
/* Get the New Thread */
|
|
mov rsi, rdx
|
|
|
|
/* Get the wait IRQL */
|
|
movzx ecx, byte ptr [edi+KTHREAD_WAIT_IRQL]
|
|
|
|
/* Do the swap with the registers correctly setup */
|
|
call KiSwapContextInternal
|
|
|
|
/* Restore the registers */
|
|
mov rbp, [rsp+0]
|
|
mov rdi, [rsp+8]
|
|
mov rsi, [rsp+16]
|
|
mov rbx, [rsp+24]
|
|
|
|
mov r10, [rsp+32]
|
|
mov r11, [rsp+40]
|
|
mov r12, [rsp+48]
|
|
mov r13, [rsp+56]
|
|
mov r14, [rsp+64]
|
|
mov r15, [rsp+72]
|
|
|
|
/* Clean stack */
|
|
add esp, 10 * 8
|
|
ret
|
|
|
|
END
|