Implement SwitchContext() and SwitchThreadStack() routines
This commit is contained in:
@@ -343,10 +343,14 @@ typedef struct _KTSS
|
|||||||
UCHAR IntDirectionMap[IOPM_DIRECTION_MAP_SIZE];
|
UCHAR IntDirectionMap[IOPM_DIRECTION_MAP_SIZE];
|
||||||
} KTSS, *PKTSS;
|
} KTSS, *PKTSS;
|
||||||
|
|
||||||
/* Exception frame definition (not available on ia32) */
|
/* Exception frame definition (not available on i686) */
|
||||||
typedef struct _KEXCEPTION_FRAME
|
typedef struct _KEXCEPTION_FRAME
|
||||||
{
|
{
|
||||||
ULONG PlaceHolder;
|
ULONG Ebp;
|
||||||
|
ULONG Ebx;
|
||||||
|
ULONG Edi;
|
||||||
|
ULONG Esi;
|
||||||
|
ULONG Return;
|
||||||
} KEXCEPTION_FRAME, *PKEXCEPTION_FRAME;
|
} KEXCEPTION_FRAME, *PKEXCEPTION_FRAME;
|
||||||
|
|
||||||
/* Thread start frame definition */
|
/* Thread start frame definition */
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ list(APPEND XTOSKRNL_SOURCE
|
|||||||
${XTOSKRNL_SOURCE_DIR}/kd/data.cc
|
${XTOSKRNL_SOURCE_DIR}/kd/data.cc
|
||||||
${XTOSKRNL_SOURCE_DIR}/kd/dbgio.cc
|
${XTOSKRNL_SOURCE_DIR}/kd/dbgio.cc
|
||||||
${XTOSKRNL_SOURCE_DIR}/kd/exports.cc
|
${XTOSKRNL_SOURCE_DIR}/kd/exports.cc
|
||||||
|
${XTOSKRNL_SOURCE_DIR}/ke/${ARCH}/dispatch.cc
|
||||||
${XTOSKRNL_SOURCE_DIR}/ke/${ARCH}/krnlinit.cc
|
${XTOSKRNL_SOURCE_DIR}/ke/${ARCH}/krnlinit.cc
|
||||||
${XTOSKRNL_SOURCE_DIR}/ke/${ARCH}/kthread.cc
|
${XTOSKRNL_SOURCE_DIR}/ke/${ARCH}/kthread.cc
|
||||||
${XTOSKRNL_SOURCE_DIR}/ke/${ARCH}/proc.cc
|
${XTOSKRNL_SOURCE_DIR}/ke/${ARCH}/proc.cc
|
||||||
|
|||||||
177
xtoskrnl/ke/amd64/dispatch.cc
Normal file
177
xtoskrnl/ke/amd64/dispatch.cc
Normal file
@@ -0,0 +1,177 @@
|
|||||||
|
/**
|
||||||
|
* PROJECT: ExectOS
|
||||||
|
* COPYRIGHT: See COPYING.md in the top level directory
|
||||||
|
* FILE: xtoskrnl/ke/amd64/dispatch.cc
|
||||||
|
* DESCRIPTION: Kernel Thread Dispatcher
|
||||||
|
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <xtos.hh>
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Entry point for thread context switching.
|
||||||
|
*
|
||||||
|
* @param CurrentThread
|
||||||
|
* Pointer to the KTHREAD structure of the current thread being suspended.
|
||||||
|
*
|
||||||
|
* @param RunLevel
|
||||||
|
* Supplies the running level at which the wait was initiated.
|
||||||
|
*
|
||||||
|
* @return This routine returns TRUE if a kernel APC is pending and can be delivered, or FALSE otherwise.
|
||||||
|
*
|
||||||
|
* @since XT 1.0
|
||||||
|
*/
|
||||||
|
XTFASTCALL
|
||||||
|
BOOLEAN
|
||||||
|
KE::Dispatcher::SwitchContext(IN PKTHREAD CurrentThread,
|
||||||
|
IN KRUNLEVEL RunLevel)
|
||||||
|
{
|
||||||
|
BOOLEAN PendingApc;
|
||||||
|
|
||||||
|
/* Save non-volatile and XMM registers to the exception frame, align the stack and invoke the switch routine */
|
||||||
|
__asm__ volatile("subq %[ExFrameSize], %%rsp\n"
|
||||||
|
"movq %%rbp, %c[ExRbp](%%rsp)\n"
|
||||||
|
"movq %%rbx, %c[ExRbx](%%rsp)\n"
|
||||||
|
"movq %%rdi, %c[ExRdi](%%rsp)\n"
|
||||||
|
"movq %%rsi, %c[ExRsi](%%rsp)\n"
|
||||||
|
"movq %%r12, %c[ExR12](%%rsp)\n"
|
||||||
|
"movq %%r13, %c[ExR13](%%rsp)\n"
|
||||||
|
"movq %%r14, %c[ExR14](%%rsp)\n"
|
||||||
|
"movq %%r15, %c[ExR15](%%rsp)\n"
|
||||||
|
"movdqa %%xmm6, %c[ExXmm6](%%rsp)\n"
|
||||||
|
"movdqa %%xmm7, %c[ExXmm7](%%rsp)\n"
|
||||||
|
"movdqa %%xmm8, %c[ExXmm8](%%rsp)\n"
|
||||||
|
"movdqa %%xmm9, %c[ExXmm9](%%rsp)\n"
|
||||||
|
"movdqa %%xmm10, %c[ExXmm10](%%rsp)\n"
|
||||||
|
"movdqa %%xmm11, %c[ExXmm11](%%rsp)\n"
|
||||||
|
"movdqa %%xmm12, %c[ExXmm12](%%rsp)\n"
|
||||||
|
"movdqa %%xmm13, %c[ExXmm13](%%rsp)\n"
|
||||||
|
"movdqa %%xmm14, %c[ExXmm14](%%rsp)\n"
|
||||||
|
"movdqa %%xmm15, %c[ExXmm15](%%rsp)\n"
|
||||||
|
"callq %P[SwitchRoutine]\n"
|
||||||
|
"movq %c[ExRbp](%%rsp), %%rbp\n"
|
||||||
|
"movq %c[ExRbx](%%rsp), %%rbx\n"
|
||||||
|
"movq %c[ExRdi](%%rsp), %%rdi\n"
|
||||||
|
"movq %c[ExRsi](%%rsp), %%rsi\n"
|
||||||
|
"movq %c[ExR12](%%rsp), %%r12\n"
|
||||||
|
"movq %c[ExR13](%%rsp), %%r13\n"
|
||||||
|
"movq %c[ExR14](%%rsp), %%r14\n"
|
||||||
|
"movq %c[ExR15](%%rsp), %%r15\n"
|
||||||
|
"movdqa %c[ExXmm6](%%rsp), %%xmm6\n"
|
||||||
|
"movdqa %c[ExXmm7](%%rsp), %%xmm7\n"
|
||||||
|
"movdqa %c[ExXmm8](%%rsp), %%xmm8\n"
|
||||||
|
"movdqa %c[ExXmm9](%%rsp), %%xmm9\n"
|
||||||
|
"movdqa %c[ExXmm10](%%rsp), %%xmm10\n"
|
||||||
|
"movdqa %c[ExXmm11](%%rsp), %%xmm11\n"
|
||||||
|
"movdqa %c[ExXmm12](%%rsp), %%xmm12\n"
|
||||||
|
"movdqa %c[ExXmm13](%%rsp), %%xmm13\n"
|
||||||
|
"movdqa %c[ExXmm14](%%rsp), %%xmm14\n"
|
||||||
|
"movdqa %c[ExXmm15](%%rsp), %%xmm15\n"
|
||||||
|
"addq %[ExFrameSize], %%rsp\n"
|
||||||
|
: "=a" (PendingApc)
|
||||||
|
: "c" (CurrentThread),
|
||||||
|
"d" (RunLevel),
|
||||||
|
[ExFrameSize] "i" (sizeof(KEXCEPTION_FRAME) - 8),
|
||||||
|
[ExR12] "i" (FIELD_OFFSET(KEXCEPTION_FRAME, R12)),
|
||||||
|
[ExR13] "i" (FIELD_OFFSET(KEXCEPTION_FRAME, R13)),
|
||||||
|
[ExR14] "i" (FIELD_OFFSET(KEXCEPTION_FRAME, R14)),
|
||||||
|
[ExR15] "i" (FIELD_OFFSET(KEXCEPTION_FRAME, R15)),
|
||||||
|
[ExRbp] "i" (FIELD_OFFSET(KEXCEPTION_FRAME, Rbp)),
|
||||||
|
[ExRbx] "i" (FIELD_OFFSET(KEXCEPTION_FRAME, Rbx)),
|
||||||
|
[ExRdi] "i" (FIELD_OFFSET(KEXCEPTION_FRAME, Rdi)),
|
||||||
|
[ExRsi] "i" (FIELD_OFFSET(KEXCEPTION_FRAME, Rsi)),
|
||||||
|
[ExXmm6] "i" (FIELD_OFFSET(KEXCEPTION_FRAME, Xmm6)),
|
||||||
|
[ExXmm7] "i" (FIELD_OFFSET(KEXCEPTION_FRAME, Xmm7)),
|
||||||
|
[ExXmm8] "i" (FIELD_OFFSET(KEXCEPTION_FRAME, Xmm8)),
|
||||||
|
[ExXmm9] "i" (FIELD_OFFSET(KEXCEPTION_FRAME, Xmm9)),
|
||||||
|
[ExXmm10] "i" (FIELD_OFFSET(KEXCEPTION_FRAME, Xmm10)),
|
||||||
|
[ExXmm11] "i" (FIELD_OFFSET(KEXCEPTION_FRAME, Xmm11)),
|
||||||
|
[ExXmm12] "i" (FIELD_OFFSET(KEXCEPTION_FRAME, Xmm12)),
|
||||||
|
[ExXmm13] "i" (FIELD_OFFSET(KEXCEPTION_FRAME, Xmm13)),
|
||||||
|
[ExXmm14] "i" (FIELD_OFFSET(KEXCEPTION_FRAME, Xmm14)),
|
||||||
|
[ExXmm15] "i" (FIELD_OFFSET(KEXCEPTION_FRAME, Xmm15)),
|
||||||
|
[SwitchRoutine] "i" (SwitchThreadStack)
|
||||||
|
: "cc", "memory", "r8", "r9", "r10", "r11");
|
||||||
|
|
||||||
|
/* Return the APC status */
|
||||||
|
return PendingApc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Switches context from current thread to the new thread.
|
||||||
|
*
|
||||||
|
* @param CurrentThread
|
||||||
|
* Pointer to the KTHREAD structure of the current thread being suspended.
|
||||||
|
*
|
||||||
|
* @param ApcBypass
|
||||||
|
* Indicates whether the APC delivery should be bypassed.
|
||||||
|
*
|
||||||
|
* @return This routine returns TRUE if a kernel APC is pending and can be delivered, or FALSE otherwise.
|
||||||
|
*
|
||||||
|
* @since XT 1.0
|
||||||
|
*/
|
||||||
|
XTFASTCALL
|
||||||
|
BOOLEAN
|
||||||
|
KE::Dispatcher::SwitchThreadContext(IN PKTHREAD CurrentThread,
|
||||||
|
IN BOOLEAN ApcBypass)
|
||||||
|
{
|
||||||
|
UNIMPLEMENTED;
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Switches the thread stack and performs necessary operations to prepare for context switching.
|
||||||
|
*
|
||||||
|
* @param CurrentThread
|
||||||
|
* Pointer to the KTHREAD structure of the current thread being suspended.
|
||||||
|
*
|
||||||
|
* @param RunLevel
|
||||||
|
* Supplies the running level at which the wait was initiated.
|
||||||
|
*
|
||||||
|
* @return This routine returns TRUE if a kernel APC is pending and can be delivered, or FALSE otherwise.
|
||||||
|
*
|
||||||
|
* @since XT 1.0
|
||||||
|
*/
|
||||||
|
XTFASTCALL
|
||||||
|
BOOLEAN
|
||||||
|
KE::Dispatcher::SwitchThreadStack(IN PKTHREAD CurrentThread,
|
||||||
|
IN KRUNLEVEL RunLevel)
|
||||||
|
{
|
||||||
|
BOOLEAN PendingApc;
|
||||||
|
|
||||||
|
/* Preserve MXCSR, synchronize with CPUs, switch stack and call the switch routine */
|
||||||
|
__asm__ volatile("pushq %%rbp\n"
|
||||||
|
"subq %[FrameSize], %%rsp\n"
|
||||||
|
"stmxcsr %c[SwMxCsr](%%rsp)\n"
|
||||||
|
"movq %%gs:%c[PrcbcCurrentThread], %%r8\n"
|
||||||
|
"BusyLoop:\n"
|
||||||
|
"cmpb $0, %c[ThrdSwapBusy](%%r8)\n"
|
||||||
|
"je ExitLoop\n"
|
||||||
|
"pause\n"
|
||||||
|
"jmp BusyLoop\n"
|
||||||
|
"ExitLoop:\n"
|
||||||
|
"movb %%dl, %c[SwApcBypass](%%rsp)\n"
|
||||||
|
"movq %%rsp, %c[ThrdStack](%%rcx)\n"
|
||||||
|
"movq %c[ThrdStack](%%r8), %%rsp\n"
|
||||||
|
"movzbl %c[SwApcBypass](%%rsp), %%edx\n"
|
||||||
|
"callq %P[SwitchRoutine]\n"
|
||||||
|
"ldmxcsr %c[SwMxCsr](%%rsp)\n"
|
||||||
|
"addq %[FrameSize], %%rsp\n"
|
||||||
|
"popq %%rbp\n"
|
||||||
|
: "=a" (PendingApc)
|
||||||
|
: "c" (CurrentThread),
|
||||||
|
"d" (RunLevel),
|
||||||
|
[FrameSize] "i" (FIELD_OFFSET(KSWITCH_FRAME, Rbp)),
|
||||||
|
[PrcbcCurrentThread] "i" (FIELD_OFFSET(KPROCESSOR_BLOCK, Prcb.CurrentThread)),
|
||||||
|
[SwApcBypass] "i" (FIELD_OFFSET(KSWITCH_FRAME, ApcBypass)),
|
||||||
|
[SwMxCsr] "i" (FIELD_OFFSET(KSWITCH_FRAME, MxCsr)),
|
||||||
|
[SwitchRoutine] "i" (SwitchThreadContext),
|
||||||
|
[ThrdStack] "i" (FIELD_OFFSET(KTHREAD, KernelStack)),
|
||||||
|
[ThrdSwapBusy] "i" (FIELD_OFFSET(KTHREAD, SwapBusy))
|
||||||
|
: "cc", "memory", "r8", "r9", "r10", "r11");
|
||||||
|
|
||||||
|
/* Return the APC status */
|
||||||
|
return PendingApc;
|
||||||
|
}
|
||||||
134
xtoskrnl/ke/i686/dispatch.cc
Normal file
134
xtoskrnl/ke/i686/dispatch.cc
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
/**
|
||||||
|
* PROJECT: ExectOS
|
||||||
|
* COPYRIGHT: See COPYING.md in the top level directory
|
||||||
|
* FILE: xtoskrnl/ke/i686/dispatch.cc
|
||||||
|
* DESCRIPTION: Kernel Thread Dispatcher
|
||||||
|
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <xtos.hh>
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Entry point for thread context switching.
|
||||||
|
*
|
||||||
|
* @param CurrentThread
|
||||||
|
* Pointer to the KTHREAD structure of the current thread being suspended.
|
||||||
|
*
|
||||||
|
* @param RunLevel
|
||||||
|
* Supplies the running level at which the wait was initiated.
|
||||||
|
*
|
||||||
|
* @return This routine returns TRUE if a kernel APC is pending and can be delivered, or FALSE otherwise.
|
||||||
|
*
|
||||||
|
* @since XT 1.0
|
||||||
|
*/
|
||||||
|
XTFASTCALL
|
||||||
|
BOOLEAN
|
||||||
|
KE::Dispatcher::SwitchContext(IN PKTHREAD CurrentThread,
|
||||||
|
IN KRUNLEVEL RunLevel)
|
||||||
|
{
|
||||||
|
BOOLEAN PendingApc;
|
||||||
|
|
||||||
|
/* Save registers to the exception frame and invoke the stack switch routine */
|
||||||
|
__asm__ volatile("subl %[ExFrameSize], %%esp\n"
|
||||||
|
"movl %%esi, %c[ExEsi](%%esp)\n"
|
||||||
|
"movl %%edi, %c[ExEdi](%%esp)\n"
|
||||||
|
"movl %%ebx, %c[ExEbx](%%esp)\n"
|
||||||
|
"movl %%ebp, %c[ExEbp](%%esp)\n"
|
||||||
|
"call %P[SwitchRoutine]\n"
|
||||||
|
"movl %c[ExEbp](%%esp), %%ebp\n"
|
||||||
|
"movl %c[ExEbx](%%esp), %%ebx\n"
|
||||||
|
"movl %c[ExEdi](%%esp), %%edi\n"
|
||||||
|
"movl %c[ExEsi](%%esp), %%esi\n"
|
||||||
|
"addl %[ExFrameSize], %%esp\n"
|
||||||
|
: "=a" (PendingApc)
|
||||||
|
: "c" (CurrentThread),
|
||||||
|
"d" (RunLevel),
|
||||||
|
[ExFrameSize] "i" (sizeof(KEXCEPTION_FRAME) - 4),
|
||||||
|
[ExEbp] "i" (FIELD_OFFSET(KEXCEPTION_FRAME, Ebp)),
|
||||||
|
[ExEbx] "i" (FIELD_OFFSET(KEXCEPTION_FRAME, Ebx)),
|
||||||
|
[ExEdi] "i" (FIELD_OFFSET(KEXCEPTION_FRAME, Edi)),
|
||||||
|
[ExEsi] "i" (FIELD_OFFSET(KEXCEPTION_FRAME, Esi)),
|
||||||
|
[SwitchRoutine] "i" (SwitchThreadStack)
|
||||||
|
: "cc", "memory");
|
||||||
|
|
||||||
|
/* Return the APC status */
|
||||||
|
return PendingApc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Switches context from current thread to the new thread.
|
||||||
|
*
|
||||||
|
* @param CurrentThread
|
||||||
|
* Pointer to the KTHREAD structure of the current thread being suspended.
|
||||||
|
*
|
||||||
|
* @param ApcBypass
|
||||||
|
* Indicates whether the APC delivery should be bypassed.
|
||||||
|
*
|
||||||
|
* @return This routine returns TRUE if a kernel APC is pending and can be delivered, or FALSE otherwise.
|
||||||
|
*
|
||||||
|
* @since XT 1.0
|
||||||
|
*/
|
||||||
|
XTFASTCALL
|
||||||
|
BOOLEAN
|
||||||
|
KE::Dispatcher::SwitchThreadContext(IN PKTHREAD CurrentThread,
|
||||||
|
IN BOOLEAN ApcBypass)
|
||||||
|
{
|
||||||
|
UNIMPLEMENTED;
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Switches the thread stack and performs necessary operations to prepare for context switching.
|
||||||
|
*
|
||||||
|
* @param CurrentThread
|
||||||
|
* Pointer to the KTHREAD structure of the current thread being suspended.
|
||||||
|
*
|
||||||
|
* @param RunLevel
|
||||||
|
* Supplies the running level at which the wait was initiated.
|
||||||
|
*
|
||||||
|
* @return This routine returns TRUE if a kernel APC is pending and can be delivered, or FALSE otherwise.
|
||||||
|
*
|
||||||
|
* @since XT 1.0
|
||||||
|
*/
|
||||||
|
XTFASTCALL
|
||||||
|
BOOLEAN
|
||||||
|
KE::Dispatcher::SwitchThreadStack(IN PKTHREAD CurrentThread,
|
||||||
|
IN KRUNLEVEL RunLevel)
|
||||||
|
{
|
||||||
|
BOOLEAN PendingApc;
|
||||||
|
|
||||||
|
/* Save old state, synchronize with CPUs, switch stack and call the switch routine */
|
||||||
|
__asm__ volatile("subl %[FrameSize], %%esp\n"
|
||||||
|
"movl %%fs:%c[PrcbcCurrentThread], %%ebx\n"
|
||||||
|
"BusyLoop:\n"
|
||||||
|
"cmpb $0, %c[ThrdSwapBusy](%%ebx)\n"
|
||||||
|
"je ExitLoop\n"
|
||||||
|
"pause\n"
|
||||||
|
"jmp BusyLoop\n"
|
||||||
|
"ExitLoop:\n"
|
||||||
|
"movl %%fs:%c[ThrdInfoExceptions], %%eax\n"
|
||||||
|
"movl %%eax, %c[SwExceptionList](%%esp)\n"
|
||||||
|
"movb %%dl, %c[SwApcBypass](%%esp)\n"
|
||||||
|
"movl %%esp, %c[ThrdStack](%%ecx)\n"
|
||||||
|
"movl %c[ThrdStack](%%ebx), %%esp\n"
|
||||||
|
"movzbl %c[SwApcBypass](%%esp), %%edx\n"
|
||||||
|
"call %P[SwitchRoutine]\n"
|
||||||
|
"addl %[FrameSize], %%esp\n"
|
||||||
|
: "=a" (PendingApc)
|
||||||
|
: "c" (CurrentThread),
|
||||||
|
"d" (RunLevel),
|
||||||
|
[FrameSize] "i" (sizeof(KSWITCH_FRAME) - 4),
|
||||||
|
[PrcbcCurrentThread] "i" (FIELD_OFFSET(KPROCESSOR_BLOCK, Prcb.CurrentThread)),
|
||||||
|
[SwApcBypass] "i" (FIELD_OFFSET(KSWITCH_FRAME, ApcBypassDisabled)),
|
||||||
|
[SwExceptionList] "i" (FIELD_OFFSET(KSWITCH_FRAME, ExceptionList)),
|
||||||
|
[SwitchRoutine] "i" (SwitchThreadContext),
|
||||||
|
[ThrdInfoExceptions] "i" (FIELD_OFFSET(THREAD_INFORMATION_BLOCK, ExceptionList)),
|
||||||
|
[ThrdStack] "i" (FIELD_OFFSET(KTHREAD, KernelStack)),
|
||||||
|
[ThrdSwapBusy] "i" (FIELD_OFFSET(KTHREAD, SwapBusy))
|
||||||
|
: "cc", "memory");
|
||||||
|
|
||||||
|
/* Return the APC status */
|
||||||
|
return PendingApc;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user