Author: sir_richard
Date: Wed Jan 20 05:05:08 2010
New Revision: 45156

URL: http://svn.reactos.org/svn/reactos?rev=45156&view=rev
Log:
[NTOS]: Implement KiSwapProcess in C.
[NTOS]: Implement KiIsNpxPresent and KiIsNpxErrataPresent in C. It's much 
clearer what these are doing now.
[NTOS]: Implement KiFlushNPXState and fix some bugs that were present in the 
ASM version, such as a wrong NPX state check.
[NTOS]: Implement working intrinsics for fxrstor, fxsave, fnsave and enable 
them for flushing. We'll update the FPU trap code to use these later.

Added:
    trunk/reactos/ntoskrnl/ke/i386/context.c   (with props)
Modified:
    trunk/reactos/ntoskrnl/include/internal/i386/intrin_i.h
    trunk/reactos/ntoskrnl/ke/i386/cpu.c
    trunk/reactos/ntoskrnl/ke/i386/ctxswitch.S
    trunk/reactos/ntoskrnl/ntoskrnl-generic.rbuild

Modified: trunk/reactos/ntoskrnl/include/internal/i386/intrin_i.h
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/i386/intrin_i.h?rev=45156&r1=45155&r2=45156&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/include/internal/i386/intrin_i.h [iso-8859-1] 
(original)
+++ trunk/reactos/ntoskrnl/include/internal/i386/intrin_i.h [iso-8859-1] Wed 
Jan 20 05:05:08 2010
@@ -13,6 +13,28 @@
     : "=m" (*X) \
     : /* no input */ \
     : "memory");
+
+FORCEINLINE
+VOID
+Ke386FxStore(IN PFX_SAVE_AREA SaveArea)
+{
+    asm volatile ("fxrstor (%0)" : : "r"(SaveArea));
+}
+
+FORCEINLINE
+VOID
+Ke386FxSave(IN PFX_SAVE_AREA SaveArea)
+{
+    asm volatile ("fxsave (%0)" : : "r"(SaveArea));
+}
+
+
+FORCEINLINE
+VOID
+Ke386FnSave(IN PFLOATING_SAVE_AREA SaveArea)
+{
+    asm volatile ("fnsave (%0); wait" : : "r"(SaveArea));
+}
 
 FORCEINLINE
 VOID

Added: trunk/reactos/ntoskrnl/ke/i386/context.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/i386/context.c?rev=45156&view=auto
==============================================================================
--- trunk/reactos/ntoskrnl/ke/i386/context.c (added)
+++ trunk/reactos/ntoskrnl/ke/i386/context.c [iso-8859-1] Wed Jan 20 05:05:08 
2010
@@ -1,0 +1,51 @@
+/*
+ * PROJECT:         ReactOS Kernel
+ * LICENSE:         BSD - See COPYING.ARM in the top level directory
+ * FILE:            ntoskrnl/ke/i386/context.c
+ * PURPOSE:         Context Switching Related Code
+ * PROGRAMMERS:     ReactOS Portable Systems Group
+ */
+
+/* INCLUDES 
*******************************************************************/
+
+#include <ntoskrnl.h>
+#define NDEBUG
+#include <debug.h>
+
+/* GLOBALS 
********************************************************************/
+
+/* FUNCTIONS 
******************************************************************/
+
+VOID
+NTAPI
+KiSwapProcess(IN PKPROCESS NewProcess,
+              IN PKPROCESS OldProcess)
+{
+    PKIPCR Pcr = (PKIPCR)KeGetPcr();
+#ifdef CONFIG_SMP
+    ULONG SetMember;
+    
+    /* Update active processor mask */
+    SetMember = Pcr->SetMember;
+    InterlockedXor(NewProcess->ActiveProcessors, SetMember);
+    InterlockedXor(OldProcess->ActiveProcessors, SetMember);
+#endif
+
+    /* Check for new LDT */
+    if (NewProcess->LdtDescriptor.LimitLow != 
OldProcess->LdtDescriptor.LimitLow)
+    {
+        /* Not handled yet */
+        UNIMPLEMENTED;
+        while (TRUE);
+    }
+    
+    /* Update CR3 */
+    __writecr3(NewProcess->DirectoryTableBase[0]);
+    
+    /* Clear GS */
+    Ke386SetGs(0);
+    
+    /* Update IOPM offset */
+    Pcr->TSS->IoMapBase = NewProcess->IopmOffset;
+}
+

Propchange: trunk/reactos/ntoskrnl/ke/i386/context.c
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: trunk/reactos/ntoskrnl/ke/i386/cpu.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/i386/cpu.c?rev=45156&r1=45155&r2=45156&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/ke/i386/cpu.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/ke/i386/cpu.c [iso-8859-1] Wed Jan 20 05:05:08 2010
@@ -944,6 +944,155 @@
     KiSaveProcessorControlState(&Prcb->ProcessorState);
 }
 
+BOOLEAN
+NTAPI
+KiIsNpxPresent(VOID)
+{
+    ULONG Cr0;
+    USHORT Magic;
+    
+    /* Set magic */
+    Magic = 0xFFFF;
+    
+    /* Read CR0 and mask out FPU flags */
+    Cr0 = __readcr0() & ~(CR0_MP | CR0_TS | CR0_EM | CR0_ET);
+    
+    /* Store on FPU stack */
+    asm volatile ("fninit;" "fnstsw %0" : "+m"(Magic));
+    
+    /* Magic should now be cleared */
+    if (Magic & 0xFF)
+    {
+        /* You don't have an FPU -- enable emulation for now */
+        __writecr0(Cr0 | CR0_EM | CR0_TS);
+        return FALSE;
+    }
+    
+    /* You have an FPU, enable it */
+    Cr0 |= CR0_ET;
+    
+    /* Enable INT 16 on 486 and higher */
+    if (KeGetCurrentPrcb()->CpuType >= 3) Cr0 |= CR0_NE;
+    
+    /* Set FPU state */
+    __writecr0(Cr0 | CR0_EM | CR0_TS);
+    return TRUE;
+}
+
+BOOLEAN
+NTAPI
+KiIsNpxErrataPresent(VOID)
+{
+    BOOLEAN ErrataPresent;
+    ULONG Cr0;
+    volatile double Value1, Value2;
+    
+    /* Disable interrupts */
+    _disable();
+    
+    /* Read CR0 and remove FPU flags */
+    Cr0 = __readcr0();
+    __writecr0(Cr0 & ~(CR0_MP | CR0_TS | CR0_EM));
+    
+    /* Initialize FPU state */
+    asm volatile ("fninit");
+    
+    /* Multiply the magic values and divide, we should get the result back */
+    Value1 = 4195835.0;
+    Value2 = 3145727.0;
+    ErrataPresent = (Value1 * Value2 / 3145727.0) != 4195835.0;
+    
+    /* Restore CR0 */
+    __writecr0(Cr0);
+    
+    /* Enable interrupts */
+    _enable();
+    
+    /* Return if there's an errata */
+    return ErrataPresent;
+}
+
+NTAPI
+VOID
+KiFlushNPXState(IN PFLOATING_SAVE_AREA SaveArea)
+{
+    ULONG EFlags, Cr0;
+    PKTHREAD Thread, NpxThread;
+    PFX_SAVE_AREA FxSaveArea;
+    
+    /* Save volatiles and disable interrupts */
+    EFlags = __readeflags();
+    _disable();
+    
+    /* Save the PCR and get the current thread */
+    Thread = KeGetCurrentThread();
+    
+    /* Check if we're already loaded */
+    if (Thread->NpxState != NPX_STATE_LOADED)
+    {
+        /* If there's nothing to load, quit */
+        if (!SaveArea) return;
+        
+        /* Need FXSR support for this */
+        ASSERT(KeI386FxsrPresent == TRUE);
+        
+        /* Check for sane CR0 */
+        Cr0 = __readcr0();
+        if (Cr0 & (CR0_MP | CR0_TS | CR0_EM))
+        {
+            /* Mask out FPU flags */
+            __writecr0(Cr0 & ~(CR0_MP | CR0_TS | CR0_EM));
+        }
+        
+        /* Get the NPX thread and check its FPU state */
+        NpxThread = KeGetCurrentPrcb()->NpxThread;
+        if ((NpxThread) && (NpxThread->NpxState == NPX_STATE_LOADED))
+        {
+            /* Get the FX frame and store the state there */
+            FxSaveArea = KiGetThreadNpxArea(NpxThread);
+            Ke386FxSave(FxSaveArea);
+            
+            /* NPX thread has lost its state */
+            NpxThread->NpxState = NPX_STATE_NOT_LOADED;
+        }
+        
+        /* Now load NPX state from the NPX area */
+        FxSaveArea = KiGetThreadNpxArea(Thread);
+        Ke386FxStore(FxSaveArea);    
+    }
+    else
+    {
+        /* Check for sane CR0 */
+        Cr0 = __readcr0();
+        if (Cr0 & (CR0_MP | CR0_TS | CR0_EM))
+        {
+            /* Mask out FPU flags */
+            __writecr0(Cr0 & ~(CR0_MP | CR0_TS | CR0_EM));
+        }
+        
+        /* Get FX frame */
+        FxSaveArea = KiGetThreadNpxArea(Thread);
+        Thread->NpxState = NPX_STATE_NOT_LOADED;
+        
+        /* Save state if supported by CPU */
+        if (KeI386FxsrPresent) Ke386FxSave(FxSaveArea);
+    }
+
+    /* Now save the FN state wherever it was requested */
+    if (SaveArea) Ke386FnSave(SaveArea);
+
+    /* Clear NPX thread */
+    KeGetCurrentPrcb()->NpxThread = NULL;
+    
+    /* Add the CR0 from the NPX frame */
+    Cr0 |= NPX_STATE_NOT_LOADED;
+    Cr0 |= FxSaveArea->Cr0NpxState;
+    __writecr0(Cr0);
+    
+    /* Restore interrupt state */
+    __writeeflags(EFlags);
+}
+
 /* PUBLIC FUNCTIONS **********************************************************/
 
 /*

Modified: trunk/reactos/ntoskrnl/ke/i386/ctxswitch.S
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/i386/ctxswitch.S?rev=45156&r1=45155&r2=45156&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/ke/i386/ctxswitch.S [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/ke/i386/ctxswitch.S [iso-8859-1] Wed Jan 20 05:05:08 
2010
@@ -17,236 +17,7 @@
 #define Running 2
 #define WrDispatchInt 0x1F
 
-Dividend: .float 4195835.0
-Divisor:  .float 3145727.0
-Result1:  .float 0
-Result2:  .float 0
-
 /* FUNCTIONS ****************************************************************/
-
-.globl _kiisnpxerratapres...@0
-.func kiisnpxerratapres...@0
-_kiisnpxerratapres...@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 _kiisnpxpres...@0
-.func kiisnpxpres...@0
-_kiisnpxpres...@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 _kiflushnpxst...@4
-.func kiflushnpxst...@4
-_kiflushnpxst...@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
 
 /*++
  * KiSwapContextInternal 
@@ -736,64 +507,6 @@
 #endif
 .endfunc
 
-.globl _kiswapproc...@8
-.func kiswapproc...@8
-_kiswapproc...@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 _ki386setupandexittov86m...@4
 .func ki386setupandexittov86m...@4
 _ki386setupandexittov86m...@4:

Modified: trunk/reactos/ntoskrnl/ntoskrnl-generic.rbuild
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ntoskrnl-generic.rbuild?rev=45156&r1=45155&r2=45156&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/ntoskrnl-generic.rbuild [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/ntoskrnl-generic.rbuild [iso-8859-1] Wed Jan 20 
05:05:08 2010
@@ -40,6 +40,7 @@
                        <directory name="i386">
                                <file>abios.c</file>
                                <file>cpu.c</file>
+                               <file>context.c</file>
                                <file>ctxswitch.S</file>
                                <file>exp.c</file>
                                <file>irqobj.c</file>


Reply via email to