reactos/ntoskrnl/ke/amd64/ctxswitch.S
Cameron Gutman c2d0d784c7 [USB-BRINGUP-TRUNK]
- Create a branch to do a proper merge of USB work from a trunk base instead of from cmake-bringup
- In the future, DO NOT under any circumstances branch another branch. This leads to merge problems!

svn path=/branches/usb-bringup-trunk/; revision=55018
2012-01-20 20:58:46 +00:00

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 <asm.inc>
#include <ksamd64.inc>
/* 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:[PcSelf]
/* 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