mirror of
https://github.com/reactos/reactos.git
synced 2025-02-24 17:34:57 +00:00
- Add support for APC-delivery after context-switch (not yet programmed)
- Detect and crash if context switch is done inside a DPC. - Switch kernel stack a bit earlier - Don't switch address space if we're still in the same process, and fix some duplicated code that was mixed up together. - Move LDT setup out-of-line. svn path=/trunk/; revision=23621
This commit is contained in:
parent
9348f70d7d
commit
233e643648
3 changed files with 69 additions and 49 deletions
|
@ -148,6 +148,7 @@ Author:
|
||||||
#define KPCR_DR6 0x428
|
#define KPCR_DR6 0x428
|
||||||
#define KPCR_DR7 0x42C
|
#define KPCR_DR7 0x42C
|
||||||
#define KPCR_SYSTEM_CALLS 0x6B8
|
#define KPCR_SYSTEM_CALLS 0x6B8
|
||||||
|
#define KPCR_PRCB_DPC_ROUTINE_ACTIVE 0x994
|
||||||
|
|
||||||
//
|
//
|
||||||
// KGDTENTRY Offsets
|
// KGDTENTRY Offsets
|
||||||
|
@ -383,6 +384,7 @@ Author:
|
||||||
#define APC_INDEX_MISMATCH 0x01
|
#define APC_INDEX_MISMATCH 0x01
|
||||||
#define IRQL_GT_ZERO_AT_SYSTEM_SERVICE 0x4A
|
#define IRQL_GT_ZERO_AT_SYSTEM_SERVICE 0x4A
|
||||||
#define UNEXPECTED_KERNEL_MODE_TRAP 0x7F
|
#define UNEXPECTED_KERNEL_MODE_TRAP 0x7F
|
||||||
|
#define ATTEMPTED_SWITCH_FROM_DPC 0xB8
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
|
@ -115,19 +115,30 @@ BadThread:
|
||||||
.globl @KiSwapContextInternal@0
|
.globl @KiSwapContextInternal@0
|
||||||
@KiSwapContextInternal@0:
|
@KiSwapContextInternal@0:
|
||||||
|
|
||||||
|
/* Save WaitIrql APC-bypass in EFLAGS */
|
||||||
|
or cl, cl
|
||||||
|
|
||||||
/* Set the Thread to running */
|
/* Set the Thread to running */
|
||||||
mov byte ptr [esi+KTHREAD_STATE], Running
|
mov byte ptr [esi+KTHREAD_STATE], Running
|
||||||
|
|
||||||
|
/* Save the flags */
|
||||||
|
pushf
|
||||||
|
|
||||||
/* Save the Exception list */
|
/* Save the Exception list */
|
||||||
push [ebx+KPCR_EXCEPTION_LIST]
|
push [ebx+KPCR_EXCEPTION_LIST]
|
||||||
|
|
||||||
|
/* DPC shouldn't be active */
|
||||||
|
cmp byte ptr [ebx+KPCR_PRCB_DPC_ROUTINE_ACTIVE], 0
|
||||||
|
jnz BugCheckDpc
|
||||||
|
|
||||||
/* Switching, disable interrupts now */
|
/* Switching, disable interrupts now */
|
||||||
cli
|
cli
|
||||||
|
|
||||||
/* Save the initial stack in EAX */
|
/* Update kernel stack */
|
||||||
mov eax, [esi+KTHREAD_INITIAL_STACK]
|
mov [edi+KTHREAD_KERNEL_STACK], esp
|
||||||
|
|
||||||
/* Save the stack limit in ecx */
|
/* Get stack pointers */
|
||||||
|
mov eax, [esi+KTHREAD_INITIAL_STACK]
|
||||||
mov ecx, [esi+KTHREAD_STACK_LIMIT]
|
mov ecx, [esi+KTHREAD_STACK_LIMIT]
|
||||||
|
|
||||||
/* Make space for the NPX Frame */
|
/* Make space for the NPX Frame */
|
||||||
|
@ -137,8 +148,7 @@ BadThread:
|
||||||
mov [ebx+KPCR_INITIAL_STACK], eax
|
mov [ebx+KPCR_INITIAL_STACK], eax
|
||||||
mov [ebx+KPCR_STACK_LIMIT], ecx
|
mov [ebx+KPCR_STACK_LIMIT], ecx
|
||||||
|
|
||||||
/* Save the stack pointer in this processors TSS */
|
/* FIXME Check and update CR0 */
|
||||||
mov ebp, [ebx+KPCR_TSS]
|
|
||||||
|
|
||||||
/* Check if this isn't V86 Mode, so we can bias the Esp0 */
|
/* Check if this isn't V86 Mode, so we can bias the Esp0 */
|
||||||
test dword ptr [eax - KTRAP_FRAME_SIZE + KTRAP_FRAME_EFLAGS], X86_EFLAGS_VM
|
test dword ptr [eax - KTRAP_FRAME_SIZE + KTRAP_FRAME_EFLAGS], X86_EFLAGS_VM
|
||||||
|
@ -150,38 +160,22 @@ BadThread:
|
||||||
NoAdjust:
|
NoAdjust:
|
||||||
|
|
||||||
/* Set new ESP0 */
|
/* Set new ESP0 */
|
||||||
mov [ebp+KTSS_ESP0], eax
|
mov ecx, [ebx+KPCR_TSS]
|
||||||
|
mov [ecx+KTSS_ESP0], eax
|
||||||
|
|
||||||
|
/* Switch to new stack */
|
||||||
|
mov esp, [esi+KTHREAD_KERNEL_STACK]
|
||||||
|
|
||||||
/* Set TEB pointer */
|
/* Set TEB pointer */
|
||||||
mov eax, [esi+KTHREAD_TEB]
|
mov eax, [esi+KTHREAD_TEB]
|
||||||
mov [ebx+KPCR_TEB], eax
|
mov [ebx+KPCR_TEB], eax
|
||||||
|
|
||||||
/* Check if address space switch is needed */
|
|
||||||
mov eax, [esi+KTHREAD_APCSTATE_PROCESS]
|
|
||||||
cmp eax, [edi+KTHREAD_APCSTATE_PROCESS]
|
|
||||||
mov eax, [eax+KPROCESS_DIRECTORY_TABLE_BASE]
|
|
||||||
|
|
||||||
/* Switch stacks */
|
|
||||||
mov [edi+KTHREAD_KERNEL_STACK], esp
|
|
||||||
mov esp, [esi+KTHREAD_KERNEL_STACK]
|
|
||||||
|
|
||||||
jz NoAddressSpaceSwitch
|
|
||||||
|
|
||||||
/* Clear gs */
|
|
||||||
xor ecx, ecx
|
|
||||||
mov gs, cx
|
|
||||||
|
|
||||||
/* Switch address space */
|
|
||||||
mov cr3, eax
|
|
||||||
mov [ebp+KTSS_CR3], eax
|
|
||||||
|
|
||||||
NoAddressSpaceSwitch:
|
|
||||||
|
|
||||||
/* Stack is OK, safe to enable interrupts now */
|
/* Stack is OK, safe to enable interrupts now */
|
||||||
sti
|
sti
|
||||||
|
|
||||||
/* Check if address space switch is needed (the result from above is valid) */
|
/* Check if address space switch is needed */
|
||||||
/* If they match, then use the fast-path and skip all this */
|
mov eax, [esi+KTHREAD_APCSTATE_PROCESS]
|
||||||
|
cmp eax, [edi+KTHREAD_APCSTATE_PROCESS]
|
||||||
jz SameProcess
|
jz SameProcess
|
||||||
|
|
||||||
/* Get the new Process. */
|
/* Get the new Process. */
|
||||||
|
@ -190,31 +184,31 @@ NoAddressSpaceSwitch:
|
||||||
/* Check if we need an LDT */
|
/* Check if we need an LDT */
|
||||||
xor eax, eax
|
xor eax, eax
|
||||||
cmp [edi+KPROCESS_LDT_DESCRIPTOR0], eax
|
cmp [edi+KPROCESS_LDT_DESCRIPTOR0], eax
|
||||||
jz NoLdt
|
jnz LdtStuff
|
||||||
|
|
||||||
/* Write the LDT Selector */
|
|
||||||
mov ecx, [ebx+KPCR_GDT]
|
|
||||||
mov eax, [edi+KPROCESS_LDT_DESCRIPTOR0]
|
|
||||||
mov [ecx+KGDT_LDT], eax
|
|
||||||
mov eax, [edi+KPROCESS_LDT_DESCRIPTOR1]
|
|
||||||
mov [ecx+KGDT_LDT+4], eax
|
|
||||||
|
|
||||||
/* Save LDT Selector */
|
|
||||||
mov eax, KGDT_LDT
|
|
||||||
|
|
||||||
NoLdt:
|
|
||||||
|
|
||||||
|
LoadLdt:
|
||||||
/* Load LDT */
|
/* Load LDT */
|
||||||
lldt ax
|
lldt ax
|
||||||
|
|
||||||
/* Get the IOPM */
|
/* Clear gs */
|
||||||
|
xor eax, eax
|
||||||
|
mov gs, ax
|
||||||
|
|
||||||
|
/* Get the address space */
|
||||||
|
mov eax, [edi+KPROCESS_DIRECTORY_TABLE_BASE]
|
||||||
|
|
||||||
|
/* Get the IOPM and TSS */
|
||||||
|
mov ebp, [ebx+KPCR_TSS]
|
||||||
mov ecx, [edi+KPROCESS_IOPM_OFFSET]
|
mov ecx, [edi+KPROCESS_IOPM_OFFSET]
|
||||||
|
|
||||||
|
/* Switch address space */
|
||||||
|
mov [ebp+KTSS_CR3], eax
|
||||||
|
mov cr3, eax
|
||||||
|
|
||||||
/* Set current IOPM offset in the TSS */
|
/* Set current IOPM offset in the TSS */
|
||||||
mov [ebp+KTSS_IOMAPBASE], cx
|
mov [ebp+KTSS_IOMAPBASE], cx
|
||||||
|
|
||||||
SameProcess:
|
SameProcess:
|
||||||
|
|
||||||
/* Set the TEB */
|
/* Set the TEB */
|
||||||
mov eax, [esi+KTHREAD_TEB]
|
mov eax, [esi+KTHREAD_TEB]
|
||||||
mov ecx, [ebx+KPCR_GDT]
|
mov ecx, [ebx+KPCR_GDT]
|
||||||
|
@ -225,13 +219,35 @@ SameProcess:
|
||||||
|
|
||||||
/* Increase context switches */
|
/* Increase context switches */
|
||||||
inc dword ptr [esi+KTHREAD_CONTEXT_SWITCHES]
|
inc dword ptr [esi+KTHREAD_CONTEXT_SWITCHES]
|
||||||
|
//inc dword ptr [esi+KPRC_PRCB_CONTEXT_SWITCHES]
|
||||||
|
|
||||||
/* Restore exception list */
|
/* Restore exception list */
|
||||||
pop [ebx+KPCR_EXCEPTION_LIST]
|
pop [ebx+KPCR_EXCEPTION_LIST]
|
||||||
|
|
||||||
/* Return */
|
/* Retore EFLAGS */
|
||||||
|
popf
|
||||||
|
|
||||||
|
/* Return no APC pending */
|
||||||
|
xor eax, eax
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
LdtStuff:
|
||||||
|
|
||||||
|
/* Write the LDT Selector */
|
||||||
|
mov ecx, [ebx+KPCR_GDT]
|
||||||
|
mov eax, [edi+KPROCESS_LDT_DESCRIPTOR0]
|
||||||
|
mov [ecx+KGDT_LDT], eax
|
||||||
|
mov eax, [edi+KPROCESS_LDT_DESCRIPTOR1]
|
||||||
|
mov [ecx+KGDT_LDT+4], eax
|
||||||
|
|
||||||
|
/* Save LDT Selector */
|
||||||
|
mov eax, KGDT_LDT
|
||||||
|
jmp LoadLdt
|
||||||
|
|
||||||
|
BugCheckDpc:
|
||||||
|
push ATTEMPTED_SWITCH_FROM_DPC
|
||||||
|
call _KeBugCheck@4
|
||||||
|
|
||||||
/*++
|
/*++
|
||||||
* KiSwapContext
|
* KiSwapContext
|
||||||
*
|
*
|
||||||
|
@ -275,12 +291,12 @@ SameProcess:
|
||||||
/* Get the New Thread */
|
/* Get the New Thread */
|
||||||
mov esi, edx
|
mov esi, edx
|
||||||
|
|
||||||
/* Get the wait IRQL */
|
|
||||||
movzx ecx, byte ptr [edi+KTHREAD_WAIT_IRQL]
|
|
||||||
|
|
||||||
/* Save it as Current thread */
|
/* Save it as Current thread */
|
||||||
mov fs:[KPCR_CURRENT_THREAD], esi
|
mov fs:[KPCR_CURRENT_THREAD], esi
|
||||||
|
|
||||||
|
/* Get the wait IRQL */
|
||||||
|
movzx ecx, byte ptr [edi+KTHREAD_WAIT_IRQL]
|
||||||
|
|
||||||
/* Do the swap with the registers correctly setup */
|
/* Do the swap with the registers correctly setup */
|
||||||
call @KiSwapContextInternal@0
|
call @KiSwapContextInternal@0
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
typedef struct _KSHARED_CTXSWITCH_FRAME
|
typedef struct _KSHARED_CTXSWITCH_FRAME
|
||||||
{
|
{
|
||||||
PVOID ExceptionList;
|
PVOID ExceptionList;
|
||||||
|
ULONG Flags;
|
||||||
PVOID RetEip;
|
PVOID RetEip;
|
||||||
} KSHARED_CTXSWITCH_FRAME, *PKSHARED_CTXSWITCH_FRAME;
|
} KSHARED_CTXSWITCH_FRAME, *PKSHARED_CTXSWITCH_FRAME;
|
||||||
|
|
||||||
|
@ -230,6 +231,7 @@ Ke386InitThreadWithContext(PKTHREAD Thread,
|
||||||
|
|
||||||
/* And set up the Context Switch Frame */
|
/* And set up the Context Switch Frame */
|
||||||
CtxSwitchFrame->RetEip = KiThreadStartup;
|
CtxSwitchFrame->RetEip = KiThreadStartup;
|
||||||
|
CtxSwitchFrame->Flags = EFLAGS_INTERRUPT_MASK;
|
||||||
CtxSwitchFrame->ExceptionList = (PVOID)0xFFFFFFFF;
|
CtxSwitchFrame->ExceptionList = (PVOID)0xFFFFFFFF;
|
||||||
|
|
||||||
/* Save back the new value of the kernel stack. */
|
/* Save back the new value of the kernel stack. */
|
||||||
|
|
Loading…
Reference in a new issue