Hi Sir Richard,

Just for the record, trunk's broken in 1st stage: 
http://build.reactos.org:8010/builders/x86_%28Test%29/builds/1208/steps/test/logs/stdio

Regards,

Gabriel.

> Date: Tue, 19 Jan 2010 09:45:30 +0000
> To: [email protected]
> From: [email protected]
> Subject: [ros-diffs] [sir_richard] 45148: [NTOS]: Implement GUI thread 
> promotion during the first GUI system call in C. This is tricky due to EBP, 
> and actually requires some tiny inline ASM magic to make it work right. 
> [NTOS]: Implement SYSENTER system calls in C as well. All system calls are 
> now handled in C. This code will be further optimized/refined soon.
> 
> Author: sir_richard
> Date: Tue Jan 19 10:45:30 2010
> New Revision: 45148
> 
> URL: http://svn.reactos.org/svn/reactos?rev=45148&view=rev
> Log:
> [NTOS]: Implement GUI thread promotion during the first GUI system call in C. 
>  This is tricky due to EBP, and actually requires some tiny inline ASM magic 
> to make it work right.
> [NTOS]: Implement SYSENTER system calls in C as well.
> 
> All system calls are now handled in C. This code will be further 
> optimized/refined soon.
> 
> Modified:
>     trunk/reactos/ntoskrnl/include/internal/ke.h
>     trunk/reactos/ntoskrnl/include/internal/trap_x.h
>     trunk/reactos/ntoskrnl/ke/i386/trap.s
>     trunk/reactos/ntoskrnl/ke/i386/traphdlr.c
> 
> Modified: trunk/reactos/ntoskrnl/include/internal/ke.h
> URL: 
> http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/ke.h?rev=45148&r1=45147&r2=45148&view=diff
> ==============================================================================
> --- trunk/reactos/ntoskrnl/include/internal/ke.h [iso-8859-1] (original)
> +++ trunk/reactos/ntoskrnl/include/internal/ke.h [iso-8859-1] Tue Jan 19 
> 10:45:30 2010
> @@ -138,6 +138,7 @@
>  extern ULONG_PTR KiBugCheckData[5];
>  extern ULONG KiFreezeFlag;
>  extern ULONG KiDPCTimeout;
> +extern PGDI_BATCHFLUSH_ROUTINE KeGdiFlushUserBatch;
>  
>  /* MACROS 
> *************************************************************************/
>  
> 
> Modified: trunk/reactos/ntoskrnl/include/internal/trap_x.h
> URL: 
> http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/trap_x.h?rev=45148&r1=45147&r2=45148&view=diff
> ==============================================================================
> --- trunk/reactos/ntoskrnl/include/internal/trap_x.h [iso-8859-1] (original)
> +++ trunk/reactos/ntoskrnl/include/internal/trap_x.h [iso-8859-1] Tue Jan 19 
> 10:45:30 2010
> @@ -436,3 +436,42 @@
>      
>      return Result;
>  }
> +
> +NTSTATUS
> +FORCEINLINE
> +KiConvertToGuiThread(VOID)
> +{
> +    NTSTATUS Result;  
> +    PVOID StackFrame;
> +
> +    /*
> +     * Converting to a GUI thread safely updates ESP in-place as well as the
> +     * current Thread->TrapFrame and EBP when KeSwitchKernelStack is called.
> +     *
> +     * However, PsConvertToGuiThread "helpfully" restores EBP to the original
> +     * caller's value, since it is considered a nonvolatile register. As 
> such,
> +     * as soon as we're back after the conversion and we try to store the 
> result
> +     * which will probably be in some stack variable (EBP-based), we'll 
> crash as
> +     * we are touching the de-allocated non-expanded stack.
> +     *
> +     * Thus we need a way to update our EBP before EBP is touched, and the 
> only
> +     * way to guarantee this is to do the call itself in assembly, use the 
> EAX
> +     * register to store the result, fixup EBP, and then let the C code 
> continue
> +     * on its merry way.
> +     *
> +     */
> +    __asm__ __volatile__
> +    (
> +        "movl %%ebp, %1\n"
> +        "subl %%esp, %1\n"
> +        "call _psconverttoguithr...@0\n"
> +        "addl %%esp, %1\n"
> +        "movl %1, %%ebp\n"
> +        "movl %%eax, %0\n"
> +        : "=r"(Result), "=r"(StackFrame)
> +        :
> +        : "%esp", "%ecx", "%edx"
> +    );
> +        
> +    return Result;
> +}
> 
> Modified: trunk/reactos/ntoskrnl/ke/i386/trap.s
> URL: 
> http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/i386/trap.s?rev=45148&r1=45147&r2=45148&view=diff
> ==============================================================================
> --- trunk/reactos/ntoskrnl/ke/i386/trap.s [iso-8859-1] (original)
> +++ trunk/reactos/ntoskrnl/ke/i386/trap.s [iso-8859-1] Tue Jan 19 10:45:30 
> 2010
> @@ -129,260 +129,30 @@
>  .endfunc
>  
>  .func KiFastCallEntry
> -TRAP_FIXUPS FastCallDrSave, FastCallDrReturn, DoNotFixupV86, DoNotFixupAbios
>  _KiFastCallEntry:
>  
> -    /* Enter the fast system call prolog */
> -    FASTCALL_PROLOG FastCallDrSave, FastCallDrReturn
> -
> -SharedCode:
> -
> -    /*
> -     * Find out which table offset to use. Converts 0x1124 into 0x10.
> -     * The offset is related to the Table Index as such: Offset = TableIndex 
> x 10
> -     */
> -    mov edi, eax
> -    shr edi, SERVICE_TABLE_SHIFT
> -    and edi, SERVICE_TABLE_MASK
> -    mov ecx, edi
> -
> -    /* Now add the thread's base system table to the offset */
> -    add edi, [esi+KTHREAD_SERVICE_TABLE]
> -
> -    /* Get the true syscall ID and check it */
> -    mov ebx, eax
> -    and eax, SERVICE_NUMBER_MASK
> -    cmp eax, [edi+SERVICE_DESCRIPTOR_LIMIT]
> -
> -    /* Invalid ID, try to load Win32K Table */
> -    jnb KiBBTUnexpectedRange
> -
> -    /* Check if this was Win32K */
> -    cmp ecx, SERVICE_TABLE_TEST
> -    jnz NotWin32K
> -
> -    /* Get the TEB */
> -    mov ecx, PCR[KPCR_TEB]
> -
> -    /* Check if we should flush the User Batch */
> -    xor ebx, ebx
> -_ReadBatch:
> -    or ebx, [ecx+TEB_GDI_BATCH_COUNT]
> -    jz NotWin32K
> -
> -    /* Flush it */
> -    push edx
> -    push eax
> -    call [_KeGdiFlushUserBatch]
> -    pop eax
> -    pop edx
> -
> -NotWin32K:
> -    /* Increase total syscall count */
> -    inc dword ptr PCR[KPCR_SYSTEM_CALLS]
> -
> -#if DBG
> -    /* Increase per-syscall count */
> -    mov ecx, [edi+SERVICE_DESCRIPTOR_COUNT]
> -    jecxz NoCountTable
> -    inc dword ptr [ecx+eax*4]
> -#endif
> -
> -    /* Users's current stack frame pointer is source */
> -NoCountTable:
> -    mov esi, edx
> -
> -    /* Allocate room for argument list from kernel stack */
> -    mov ebx, [edi+SERVICE_DESCRIPTOR_NUMBER]
> -    xor ecx, ecx
> -    mov cl, [eax+ebx]
> -
> -    /* Get pointer to function */
> -    mov edi, [edi+SERVICE_DESCRIPTOR_BASE]
> -    mov ebx, [edi+eax*4]
> -
> -    /* Allocate space on our stack */
> -    sub esp, ecx
> -
> -    /* Set the size of the arguments and the destination */
> -    shr ecx, 2
> -    mov edi, esp
> -
> -    /* Make sure we're within the User Probe Address */
> -    cmp esi, _MmUserProbeAddress
> -    jnb AccessViolation
> -
> -_CopyParams:
> -    /* Copy the parameters */
> -    rep movsd
> -
> -    /* Do the System Call */
> -    call ebx
> -
> -AfterSysCall:
> -#if DBG
> -    /* Make sure the user-mode call didn't return at elevated IRQL */
> -    test byte ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
> -    jz SkipCheck
> -    mov esi, eax                /* We need to save the syscall's return val 
> */
> -    call _kegetcurrenti...@0
> -    or al, al
> -    jnz InvalidIrql
> -    mov eax, esi                /* Restore it */
> -
> -    /* Get our temporary current thread pointer for sanity check */
> -    mov ecx, PCR[KPCR_CURRENT_THREAD]
> -
> -    /* Make sure that we are not attached and that APCs are not disabled */
> -    mov dl, [ecx+KTHREAD_APC_STATE_INDEX]
> -    or dl, dl
> -    jnz InvalidIndex
> -    mov edx, [ecx+KTHREAD_COMBINED_APC_DISABLE]
> -    or edx, edx
> -    jnz InvalidIndex
> -#endif
> -
> -SkipCheck:
> -
> -    /* Deallocate the kernel stack frame  */
> -    mov esp, ebp
> -
> -KeReturnFromSystemCall:
> -
> -    /* Get the Current Thread */
> -    mov ecx, PCR[KPCR_CURRENT_THREAD]
> -
> -    /* Restore the old trap frame pointer */
> -    mov edx, [ebp+KTRAP_FRAME_EDX]
> -    mov [ecx+KTHREAD_TRAP_FRAME], edx
> +    /* Sane FS segment */
> +    mov ecx, KGDT_R0_PCR
> +    mov fs, cx
>      
> -    /* Exit the system call */
> -    mov ecx, ebp
> -    mov edx, eax
> -    jmp @kiservicee...@8
> -.endfunc
> -
> -KiBBTUnexpectedRange:
> -
> -    /* If this isn't a Win32K call, fail */
> -    cmp ecx, SERVICE_TABLE_TEST
> -    jne InvalidCall
> -
> -    /* Set up Win32K Table */
> -    push edx
> -    push ebx
> -    call _psconverttoguithr...@0
> -
> -    /* Check return code */
> -    or eax, eax
> -
> -    /* Restore registers */
> -    pop eax
> -    pop edx
> -
> -    /* Reset trap frame address */
> -    mov ebp, esp
> -    mov [esi+KTHREAD_TRAP_FRAME], ebp
> -
> -    /* Try the Call again, if we suceeded */
> -    jz SharedCode
> -
> -    /*
> -     * The Shadow Table should have a special byte table which tells us
> -     * whether we should return FALSE, -1 or STATUS_INVALID_SYSTEM_SERVICE.
> -     */
> -
> -    /* Get the table limit and base */
> -    lea edx, _KeServiceDescriptorTableShadow + SERVICE_TABLE_TEST
> -    mov ecx, [edx+SERVICE_DESCRIPTOR_LIMIT]
> -    mov edx, [edx+SERVICE_DESCRIPTOR_BASE]
> -
> -    /* Get the table address and add our index into the array */
> -    lea edx, [edx+ecx*4]
> -    and eax, SERVICE_NUMBER_MASK
> -    add edx, eax
> -
> -    /* Find out what we should return */
> -    movsx eax, byte ptr [edx]
> -    or eax, eax
> -
> -    /* Return either 0 or -1, we've set it in EAX */
> -    jle KeReturnFromSystemCall
> -
> -    /* Set STATUS_INVALID_SYSTEM_SERVICE */
> -    mov eax, STATUS_INVALID_SYSTEM_SERVICE
> -    jmp KeReturnFromSystemCall
> -
> -InvalidCall:
> -
> -    /* Invalid System Call */
> -    mov eax, STATUS_INVALID_SYSTEM_SERVICE
> -    jmp KeReturnFromSystemCall
> -
> -AccessViolation:
> -
> -    /* Check if this came from kernel-mode */
> -    test byte ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
> -
> -    /* It's fine, go ahead with it */
> -    jz _CopyParams
> -
> -    /* Caller sent invalid parameters, fail here */
> -    mov eax, STATUS_ACCESS_VIOLATION
> -    jmp AfterSysCall
> -
> -BadStack:
> -
> -    /* Restore ESP0 stack */
> -    mov ecx, PCR[KPCR_TSS]
> -    mov esp, ss:[ecx+KTSS_ESP0]
> -
> -    /* Generate V86M Stack for Trap 6 */
> -    push 0
> -    push 0
> -    push 0
> -    push 0
> -
> -    /* Generate interrupt stack for Trap 6 */
> -    push KGDT_R3_DATA + RPL_MASK
> -    push 0
> -    push 0x20202
> -    push KGDT_R3_CODE + RPL_MASK
> -    push 0
> -    jmp _KiTrap06
> -
> -#if DBG
> -InvalidIrql:
> -    /* Save current IRQL */
> -    push PCR[KPCR_IRQL]
> -
> -    /* Set us at passive */
> -    mov dword ptr PCR[KPCR_IRQL], 0
> -    cli
> -
> -    /* Bugcheck */
> -    push 0
> -    push 0
> -    push eax
> -    push ebx
> -    push IRQL_GT_ZERO_AT_SYSTEM_SERVICE
> -    call _kebugchec...@20
> -
> -InvalidIndex:
> -
> -    /* Get the index and APC state */
> -    movzx eax, byte ptr [ecx+KTHREAD_APC_STATE_INDEX]
> -    mov edx, [ecx+KTHREAD_COMBINED_APC_DISABLE]
> -
> -    /* Bugcheck */
> -    push 0
> -    push edx
> -    push eax
> -    push ebx
> -    push APC_INDEX_MISMATCH
> -    call _kebugchec...@20
> -    ret
> -#endif
> +    /* Sane stack and frame */
> +    mov esp, PCR[KPCR_TSS]
> +    mov esp, [esp+KTSS_ESP0]
> +    
> +    /* Make space for trap frame on the stack */
> +    sub esp, KTRAP_FRAME_V86_ES
> +    
> +    /* Save EBP, EBX, ESI, EDI only! */
> +    mov [esp+KTRAP_FRAME_EBX], ebx
> +    mov [esp+KTRAP_FRAME_ESI], esi
> +    mov [esp+KTRAP_FRAME_EDI], edi
> +    mov [esp+KTRAP_FRAME_EBP], ebp
> +    
> +    /* Call C handler -- note that EDX is the user stack, and EAX the 
> syscall */
> +    mov ecx, esp
> +    add edx, 8
> +    jmp _KiFastCallEntryHandler
> +.endfunc
>  
>  .func kei386eoihel...@0
>  _kei386eoihel...@0:
> 
> Modified: trunk/reactos/ntoskrnl/ke/i386/traphdlr.c
> URL: 
> http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/i386/traphdlr.c?rev=45148&r1=45147&r2=45148&view=diff
> ==============================================================================
> --- trunk/reactos/ntoskrnl/ke/i386/traphdlr.c [iso-8859-1] (original)
> +++ trunk/reactos/ntoskrnl/ke/i386/traphdlr.c [iso-8859-1] Tue Jan 19 
> 10:45:30 2010
> @@ -1465,6 +1465,7 @@
>      }
>      
>      /* Check for syscall fault */
> +#if 0
>      if ((TrapFrame->Eip == (ULONG_PTR)CopyParams) ||
>          (TrapFrame->Eip == (ULONG_PTR)ReadBatch))
>      {
> @@ -1472,7 +1473,7 @@
>          UNIMPLEMENTED;
>          while (TRUE);
>      }
> -
> +#endif
>      /* Check for VDM trap */
>      ASSERT((KiVdmTrap(TrapFrame)) == FALSE);
>      
> @@ -1725,9 +1726,14 @@
>                  goto ExitCall;
>              }
>  
> -            /* GUI calls are not yet supported */
> -            UNIMPLEMENTED;
> -            while (TRUE);
> +            /* Convert us to a GUI thread -- must wrap in ASM to get new EBP 
> */        
> +            Result = KiConvertToGuiThread();
> +            if (__builtin_expect(!NT_SUCCESS(Result), 0))
> +            {
> +                /* Figure out how we should fail to the user */
> +                UNIMPLEMENTED;
> +                while (TRUE);
> +            }
>              
>              /* Try the call again */
>              continue;
> @@ -1741,8 +1747,7 @@
>      if (__builtin_expect(Offset & SERVICE_TABLE_TEST, 0))
>      {
>          /* Get the batch count and flush if necessary */
> -        UNIMPLEMENTED;
> -        while (TRUE);
> +        if (NtCurrentTeb()->GdiBatchCount) KeGdiFlushUserBatch();
>      }
>      
>      /* Increase system call count */
> @@ -1816,6 +1821,39 @@
>      /* Enable interrupts and make the call */
>      _enable();
>      KiSystemCall(ServiceNumber, Arguments);   
> +}
> +
> +VOID
> +__attribute__((regparm(3)))
> +KiFastCallEntryHandler(IN ULONG ServiceNumber,
> +                       IN PVOID Arguments,
> +                       IN PKTRAP_FRAME TrapFrame)
> +{
> +    PKTHREAD Thread;
> +        
> +    /* Fixup segments */
> +    Ke386SetDs(KGDT_R3_DATA | RPL_MASK);
> +    Ke386SetEs(KGDT_R3_DATA | RPL_MASK);
> +    
> +    /* Set up a fake INT Stack and enable interrupts */
> +    TrapFrame->HardwareSegSs = KGDT_R3_DATA | RPL_MASK;
> +    TrapFrame->HardwareEsp = (ULONG_PTR)Arguments - 8; // Stack is 2 frames 
> down
> +    TrapFrame->EFlags = __readeflags() | EFLAGS_INTERRUPT_MASK;
> +    TrapFrame->SegCs = KGDT_R3_CODE | RPL_MASK;
> +    TrapFrame->Eip = SharedUserData->SystemCallReturn;
> +    __writeeflags(0x2);
> +    
> +    /* Get the current thread */
> +    Thread = KeGetCurrentThread();
> +
> +    /* Call the shared handler (inline) */
> +    KiSystemCallHandler(TrapFrame,
> +                        ServiceNumber,
> +                        Arguments,
> +                        Thread,
> +                        UserMode,
> +                        Thread->PreviousMode,
> +                        KGDT_R3_TEB | RPL_MASK);
>  }
>  
>  VOID
> 
> 
                                          
_________________________________________________________________
25 Gygabite gratis online. Archivia e condividi i tuoi file!
http://www.windowslive.it/skyDrive.aspx
_______________________________________________
Ros-dev mailing list
[email protected]
http://www.reactos.org/mailman/listinfo/ros-dev

Reply via email to