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