#define Running 2
#define WrDispatchInt 0x1F
-Dividend: .float 4195835.0
-Divisor: .float 3145727.0
-Result1: .float 0
-Result2: .float 0
-
/* FUNCTIONS ****************************************************************/
-.globl _KiIsNpxErrataPresent@0
-.func KiIsNpxErrataPresent@0
-_KiIsNpxErrataPresent@0:
-
- /* Disable interrupts */
- cli
-
- /* Get CR0 and mask out FPU flags */
- mov eax, cr0
- mov ecx, eax
- and eax, ~(CR0_MP + CR0_TS + CR0_EM)
- mov cr0, eax
-
- /* Initialize the FPU */
- fninit
-
- /* Do the divison and inverse multiplication */
- fld qword ptr Dividend
- fstp qword ptr Result1
- fld qword ptr Divisor
- fstp qword ptr Result2
- fld qword ptr Result1
- fdiv qword ptr Result2
- fmul qword ptr Result2
-
- /* Do the compare and check flags */
- fcomp qword ptr Result1
- fstsw ax
- sahf
-
- /* Restore CR0 and interrupts */
- mov cr0, ecx
- sti
-
- /* Return errata status */
- xor eax, eax
- jz NoErrata
- inc eax
-
-NoErrata:
- ret
-.endfunc
-
-.globl _KiIsNpxPresent@0
-.func KiIsNpxPresent@0
-_KiIsNpxPresent@0:
-
- /* Save stack */
- push ebp
-
- /* Get CR0 and mask out FPU flags */
- mov eax, cr0
- and eax, ~(CR0_MP + CR0_TS + CR0_EM + CR0_ET)
-
- /* Initialize the FPU and assume FALSE for return */
- xor edx, edx
- fninit
-
- /* Save magic value on stack */
- mov ecx, 0x42424242
- push ecx
-
- /* Setup stack for FPU store */
- mov ebp ,esp
- fnstsw [ebp]
-
- /* Now check if our magic got cleared */
- cmp byte ptr [ebp], 0
- jnz NoFpu
-
- /* Enable FPU, set return to TRUE */
- or eax, CR0_ET
- mov edx, 1
-
- /* If this is a 486 or higher, enable INT 16 as well */
- cmp dword ptr fs:KPCR_PRCB_CPU_TYPE, 3
- jbe NoFpu
- or eax, CR0_NE
-
-NoFpu:
- /* Set emulation enabled during the first boot phase and set the CR0 */
- or eax, (CR0_EM + CR0_TS)
- mov cr0, eax
-
- /* Restore stack */
- pop eax
- pop ebp
-
- /* Return true or false */
- mov eax, edx
- ret
-.endfunc
-
-.globl _KiFlushNPXState@4
-.func KiFlushNPXState@4
-_KiFlushNPXState@4:
-
- /* Save volatiles and disable interrupts */
- push esi
- push edi
- push ebx
- pushfd
- cli
-
- /* Save the PCR and get the current thread */
- mov edi, fs:[KPCR_SELF]
- mov esi, [edi+KPCR_CURRENT_THREAD]
-
- /* Check if we're already loaded */
- cmp byte ptr [esi+KTHREAD_NPX_STATE], NPX_STATE_LOADED
- je IsValid
-
- /* Check if we're supposed to get it */
- cmp dword ptr [esp+20], 0
- je Return
-
-#if DBG
- /* Assert Fxsr support */
- test byte ptr _KeI386FxsrPresent, 1
- jnz AssertOk
- int 3
-AssertOk:
-#endif
-
- /* Get CR0 and test if it's valid */
- mov ebx, cr0
- test bl, CR0_MP + CR0_TS + CR0_EM
- jz Cr0OK
-
- /* Enable fnsave to work */
- and ebx, ~(CR0_MP + CR0_TS + CR0_EM)
- mov cr0, ebx
-
-Cr0OK:
- /* Check if we are the NPX Thread */
- mov eax, [edi+KPCR_NPX_THREAD]
- or eax, eax
- jz DontSave
-
- /* Check if it's not loaded */
- cmp byte ptr [eax+KTHREAD_NPX_STATE], NPX_STATE_NOT_LOADED
- jnz DontSave
-
-#if DBG
- /* We are the NPX Thread with an unloaded NPX State... this isn't normal! */
- int 3
-#endif
-
- /* Save the NPX State */
- mov ecx, [eax+KTHREAD_INITIAL_STACK]
- sub ecx, NPX_FRAME_LENGTH
- fxsave [ecx]
- mov byte ptr [eax+KTHREAD_NPX_STATE], NPX_STATE_NOT_LOADED
-
-DontSave:
- /* Load the NPX State */
- mov ecx, [esi+KTHREAD_INITIAL_STACK]
- sub ecx, NPX_FRAME_LENGTH
- fxrstor [ecx]
-
- /* Get the CR0 state and destination */
- mov edx, [ecx+FN_CR0_NPX_STATE]
- mov ecx, [esp+20]
- jmp DoneLoad
-
-IsValid:
- /* We already have a valid state, flush it */
- mov ebx, cr0
- test bl, CR0_MP + CR0_TS + CR0_EM
- jz Cr0OK2
-
- /* Enable fnsave to work */
- and ebx, ~(CR0_MP + CR0_TS + CR0_EM)
- mov cr0, ebx
-
-Cr0OK2:
- /* Get the kernel stack */
- mov ecx, [esi+KTHREAD_INITIAL_STACK]
- test byte ptr _KeI386FxsrPresent, 1
- lea ecx, [ecx-NPX_FRAME_LENGTH]
-
- /* Set the NPX State */
- mov byte ptr [esi+KTHREAD_NPX_STATE], NPX_STATE_NOT_LOADED
-
- /* Get Cr0 */
- mov edx, [ecx+FN_CR0_NPX_STATE]
- jz DoneLoad
-
- /* Save the FX State */
- fxsave [ecx]
-
- /* Check if we also have to save it in the parameter */
- mov ecx, [esp+20]
- jecxz NoSave
-
-DoneLoad:
- /* Save the Fn state in the parameter we got */
- fnsave [ecx]
- fwait
-
-NoSave:
- /* Clear eax */
- xor eax, eax
-
- /* Add NPX State */
- or ebx, NPX_STATE_NOT_LOADED
-
- /* Clear the NPX thread */
- mov [edi+KPCR_NPX_THREAD], eax
-
- /* Add saved CR0 into NPX State, and set it */
- or ebx, edx
- mov cr0, ebx
-
- /* Re-enable interrupts and return */
-Return:
- popf
- pop ebx
- pop edi
- pop esi
- ret 4
-
-.endfunc
-
-/*++
- * 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.
- *
- *--*/
- .func KiThreadStartup@156
-.globl _KiThreadStartup@156
-_KiThreadStartup@156:
-
- /*
- * 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 ebx, ebx
- xor esi, esi
- xor edi, edi
- xor ebp, ebp
-
- /* It's now safe to go to APC */
- mov ecx, APC_LEVEL
- call @KfLowerIrql@4
-
- /*
- * Call the System Routine which is right on our stack now.
- * After we pop the pointer, the Start Routine/Context will be on the
- * stack, as parameters to the System Routine
- */
- pop eax
- call eax
-
- /* The thread returned... was it a user-thread? */
- pop ecx
- or ecx, ecx
- jz BadThread
-
- /* Yes it was, set our trapframe for the System Call Exit Dispatcher */
- mov ebp, esp
-
- /* Exit back to user-mode */
- jmp _KiServiceExit2
-
-BadThread:
-
- /* A system thread returned...this is very bad! */
- int 3
-.endfunc
-
/*++
* KiSwapContextInternal
*
#endif
.endfunc
-.globl _KiSwapProcess@8
-.func KiSwapProcess@8
-_KiSwapProcess@8:
-
- /* Get process pointers */
- mov edx, [esp+4]
- mov eax, [esp+8]
-
-#ifdef CONFIG_SMP
- /* Update active processors */
- mov ecx, fs:[KPCR_SET_MEMBER]
- lock xor [edx+KPROCESS_ACTIVE_PROCESSORS], ecx
- lock xor [eax+KPROCESS_ACTIVE_PROCESSORS], ecx
-
- /* Sanity check */
-#if DBG
- test [edx+KPROCESS_ACTIVE_PROCESSORS], ecx
- jz WrongCpu1
- test [eax+KPROCESS_ACTIVE_PROCESSORS], ecx
- jnz WrongCpu2
-#endif
-#endif
-
- /* Check if their LDTs changed */
- mov ecx, [edx+KPROCESS_LDT_DESCRIPTOR0]
- or ecx, [eax+KPROCESS_LDT_DESCRIPTOR0]
- jnz NewLdt
-
- /* Update CR3 */
- mov eax, [edx+KPROCESS_DIRECTORY_TABLE_BASE]
- mov cr3, eax
-
- /* Get the KTSS */
- mov ecx, fs:[KPCR_TSS]
-
- /* Clear GS on process swap */
- xor eax, eax
- mov gs, ax
-
- /* Update IOPM offset */
- mov ax, [edx+KPROCESS_IOPM_OFFSET]
- mov [ecx+KTSS_IOMAPBASE], ax
-
- /* Return */
- ret 8
-
-NewLdt:
- /* FIXME: TODO */
- int 3
-
-#if DBG
-WrongCpu1:
- int 3
-WrongCpu2:
- int 3
-#endif
-.endfunc
-
.globl _Ki386SetupAndExitToV86Mode@4
.func Ki386SetupAndExitToV86Mode@4
_Ki386SetupAndExitToV86Mode@4: