1c2c66affSColin Finck/* 2c2c66affSColin Finck * COPYRIGHT: See COPYING in the top level directory 3c2c66affSColin Finck * PROJECT: ReactOS kernel 4c2c66affSColin Finck * FILE: ntdll/dispatch/amd64/dispatch.S 5c2c66affSColin Finck * PURPOSE: Usermode dispatcher stubs 6c2c66affSColin Finck * 7c2c66affSColin Finck * PROGRAMMER: Timo kreuzer (timo.kreuzer@reactos.org) 8c2c66affSColin Finck */ 9c2c66affSColin Finck 10c2c66affSColin Finck/* INCLUDES ******************************************************************/ 11c2c66affSColin Finck 12c2c66affSColin Finck#include <asm.inc> 13c2c66affSColin Finck#include <ksamd64.inc> 14c2c66affSColin Finck 15c2c66affSColin FinckEXTERN NtContinue:PROC 16c2c66affSColin FinckEXTERN LdrpInit:PROC 17fdc1261fSTimo KreuzerEXTERN ZwCallbackReturn:PROC 18fdc1261fSTimo KreuzerEXTERN RtlRaiseStatus:PROC 19c2c66affSColin Finck 20c2c66affSColin Finck.code 21c2c66affSColin Finck 22c2c66affSColin FinckPUBLIC LdrInitializeThunk 23c2c66affSColin Finck.PROC LdrInitializeThunk 24c2c66affSColin Finck mov rbp, 0 25c2c66affSColin Finck .setframe rbp, 0 26c2c66affSColin Finck .endprolog 27c2c66affSColin Finck 28c2c66affSColin Finck /* First parameter is the APC context */ 29c2c66affSColin Finck mov rcx, r9 30c2c66affSColin Finck jmp LdrpInit 31c2c66affSColin Finck 32c2c66affSColin Finck.ENDP 33c2c66affSColin Finck 34c2c66affSColin FinckPUBLIC KiUserApcDispatcher 35c2c66affSColin Finck.PROC KiUserApcDispatcher 36*29721ac5STimo Kreuzer 37*29721ac5STimo Kreuzer /* The stack is set up with a UAPC_FRAME, which ends with a MACHINE_FRAME */ 38*29721ac5STimo Kreuzer .PUSHFRAME 39*29721ac5STimo Kreuzer .ALLOCSTACK CONTEXT_FRAME_LENGTH 40*29721ac5STimo Kreuzer 41*29721ac5STimo Kreuzer /* The stack points to a CONTEXT structure. 42*29721ac5STimo Kreuzer Create unwind ops for all nonvolatile registers */ 43*29721ac5STimo Kreuzer .SAVEREG rbx, CxRbx 44*29721ac5STimo Kreuzer .SAVEREG rbp, CxRbp 45*29721ac5STimo Kreuzer .SAVEREG rsi, CxRsi 46*29721ac5STimo Kreuzer .SAVEREG rdi, CxRdi 47*29721ac5STimo Kreuzer .SAVEREG r12, CxR12 48*29721ac5STimo Kreuzer .SAVEREG r13, CxR13 49*29721ac5STimo Kreuzer .SAVEREG r14, CxR14 50*29721ac5STimo Kreuzer .SAVEREG r15, CxR15 51*29721ac5STimo Kreuzer .SAVEXMM128 xmm6, CxXmm6 52*29721ac5STimo Kreuzer .SAVEXMM128 xmm7, CxXmm7 53*29721ac5STimo Kreuzer .SAVEXMM128 xmm8, CxXmm8 54*29721ac5STimo Kreuzer .SAVEXMM128 xmm9, CxXmm9 55*29721ac5STimo Kreuzer .SAVEXMM128 xmm10, CxXmm10 56*29721ac5STimo Kreuzer .SAVEXMM128 xmm11, CxXmm11 57*29721ac5STimo Kreuzer .SAVEXMM128 xmm12, CxXmm12 58*29721ac5STimo Kreuzer .SAVEXMM128 xmm13, CxXmm13 59*29721ac5STimo Kreuzer .SAVEXMM128 xmm14, CxXmm14 60*29721ac5STimo Kreuzer .SAVEXMM128 xmm15, CxXmm15 61*29721ac5STimo Kreuzer 62c2c66affSColin Finck .endprolog 63c2c66affSColin Finck /* We enter with a 16 byte aligned stack */ 64c2c66affSColin Finck 65c2c66affSColin Finck mov rcx, [rsp + CONTEXT_P1Home] /* NormalContext */ 66c2c66affSColin Finck mov rdx, [rsp + CONTEXT_P2Home] /* SystemArgument1 */ 67c2c66affSColin Finck mov r8, [rsp + CONTEXT_P3Home] /* SystemArgument2 */ 68c2c66affSColin Finck lea r9, [rsp] /* Context */ 69c2c66affSColin Finck call qword ptr [rsp + CONTEXT_P4Home] /* NormalRoutine */ 70c2c66affSColin Finck 71c2c66affSColin Finck /* NtContinue(Context, TRUE); */ 72c2c66affSColin Finck lea rcx, [rsp] 73c2c66affSColin Finck mov dl, 1 74c2c66affSColin Finck call NtContinue 75c2c66affSColin Finck 76c2c66affSColin Finck nop 77c2c66affSColin Finck int 3 78c2c66affSColin Finck.ENDP 79c2c66affSColin Finck 80c2c66affSColin Finck 81c2c66affSColin FinckPUBLIC KiRaiseUserExceptionDispatcher 82c2c66affSColin Finck.PROC KiRaiseUserExceptionDispatcher 83c2c66affSColin Finck .endprolog 84c2c66affSColin Finck int 3 85c2c66affSColin Finck 86c2c66affSColin Finck.ENDP 87c2c66affSColin Finck 88c2c66affSColin FinckPUBLIC KiUserCallbackDispatcher 89c2c66affSColin Finck.PROC KiUserCallbackDispatcher 90fdc1261fSTimo Kreuzer 91ff7035d9SHervé Poussineau /* The stack is set up with a UCALLOUT_FRAME */ 92ff7035d9SHervé Poussineau /* The frame ends with a MACHINE_FRAME. */ 93fdc1261fSTimo Kreuzer .PUSHFRAME 94fdc1261fSTimo Kreuzer 95ff7035d9SHervé Poussineau /* This is for the Home space, Buffer, Length and ApiNumber */ 96ae4ce99eSHervé Poussineau .ALLOCSTACK (6 * 8) 97fdc1261fSTimo Kreuzer .ENDPROLOG 98fdc1261fSTimo Kreuzer 99fdc1261fSTimo Kreuzer#if DBG 100ff7035d9SHervé Poussineau /* We enter the function with a fully setup stack, so it must be aligned! */ 101fdc1261fSTimo Kreuzer test rsp, 15 102fdc1261fSTimo Kreuzer jz AlignmentOk 103fdc1261fSTimo Kreuzer int HEX(2C) 104fdc1261fSTimo KreuzerAlignmentOk: 105fdc1261fSTimo Kreuzer#endif 106fdc1261fSTimo Kreuzer 107ff7035d9SHervé Poussineau /* Get the parameters from the callout frame */ 108fdc1261fSTimo Kreuzer mov rcx, [rsp + CkBuffer] 109fdc1261fSTimo Kreuzer mov edx, [rsp + CkLength] 110fdc1261fSTimo Kreuzer mov r8d, [rsp + CkApiNumber] 111fdc1261fSTimo Kreuzer 112ff7035d9SHervé Poussineau /* Get the callback table */ 113fdc1261fSTimo Kreuzer mov rax, gs:[TePeb] 114fdc1261fSTimo Kreuzer mov r9, [rax + PeKernelCallbackTable] 115fdc1261fSTimo Kreuzer 116ff7035d9SHervé Poussineau /* Call the routine */ 117fdc1261fSTimo Kreuzer call qword ptr [r9 + r8 * 8] 118fdc1261fSTimo Kreuzer 119ff7035d9SHervé Poussineau /* Return from callback */ 120fdc1261fSTimo Kreuzer xor ecx, ecx 121fdc1261fSTimo Kreuzer xor edx, edx 122fdc1261fSTimo Kreuzer mov r8d, eax 123fdc1261fSTimo Kreuzer call ZwCallbackReturn 124fdc1261fSTimo Kreuzer 125ff7035d9SHervé Poussineau /* Save callback return value */ 126fdc1261fSTimo Kreuzer mov esi, eax 127fdc1261fSTimo Kreuzer 128ff7035d9SHervé Poussineau /* Raise status */ 129fdc1261fSTimo KreuzerStatusRaise: 130fdc1261fSTimo Kreuzer mov ecx, esi 131fdc1261fSTimo Kreuzer call RtlRaiseStatus 132fdc1261fSTimo Kreuzer jmp StatusRaise 133c2c66affSColin Finck 134c2c66affSColin Finck.ENDP 135c2c66affSColin Finck 1362a8c680dSTimo Kreuzer/* 1372a8c680dSTimo Kreuzer BOOLEAN 1382a8c680dSTimo Kreuzer NTAPI 1392a8c680dSTimo Kreuzer RtlDispatchException( 1402a8c680dSTimo Kreuzer _In_ PEXCEPTION_RECORD ExceptionRecord, 1412a8c680dSTimo Kreuzer _In_ PCONTEXT ContextRecord); 1422a8c680dSTimo Kreuzer */ 1432a8c680dSTimo KreuzerEXTERN RtlDispatchException:PROC 1442a8c680dSTimo Kreuzer 1452a8c680dSTimo Kreuzer/* 1462a8c680dSTimo Kreuzer NTSTATUS 1472a8c680dSTimo Kreuzer NTAPI 1482a8c680dSTimo Kreuzer ZwContinue( 1492a8c680dSTimo Kreuzer _In_ PCONTEXT Context, 1502a8c680dSTimo Kreuzer _In_ BOOLEAN TestAlert); 1512a8c680dSTimo Kreuzer */ 1522a8c680dSTimo KreuzerEXTERN ZwContinue:PROC 1532a8c680dSTimo Kreuzer 1542a8c680dSTimo Kreuzer/* 1552a8c680dSTimo Kreuzer NTSTATUS 1562a8c680dSTimo Kreuzer NTAPI 1572a8c680dSTimo Kreuzer ZwRaiseException( 1582a8c680dSTimo Kreuzer _In_ PEXCEPTION_RECORD ExceptionRecord, 1592a8c680dSTimo Kreuzer _In_ PCONTEXT Context, 1602a8c680dSTimo Kreuzer _In_ BOOLEAN SearchFrames); 1612a8c680dSTimo Kreuzer */ 1622a8c680dSTimo KreuzerEXTERN ZwRaiseException:PROC 1632a8c680dSTimo Kreuzer 1642a8c680dSTimo Kreuzer/* 1652a8c680dSTimo Kreuzer VOID 1662a8c680dSTimo Kreuzer NTAPI 1672a8c680dSTimo Kreuzer RtlRaiseStatus( 1682a8c680dSTimo Kreuzer _In_ PEXCEPTION_RECORD ExceptionRecord); 1692a8c680dSTimo Kreuzer */ 1702a8c680dSTimo KreuzerEXTERN RtlRaiseException:PROC 1712a8c680dSTimo Kreuzer 1722a8c680dSTimo Kreuzer/* 1732a8c680dSTimo Kreuzer VOID 1742a8c680dSTimo Kreuzer KiUserExceptionDispatcher( 1752a8c680dSTimo Kreuzer CONTEXT ContextRecord<rcx>, 1762a8c680dSTimo Kreuzer PEXCEPTION_RECORD ExceptionRecord<rdx>); 1772a8c680dSTimo Kreuzer 1782a8c680dSTimo Kreuzer This function is called with the following stack layout: 1792a8c680dSTimo Kreuzer CONTEXT ContextRecord <- RSP, RCX 1802a8c680dSTimo Kreuzer EXCEPTION_RECORD ExceptionRecord <- RDX 1812a8c680dSTimo Kreuzer ULONG64 Alignment 1822a8c680dSTimo Kreuzer MACHINE_FRAME MachineFrame 1832a8c680dSTimo Kreuzer */ 184c2c66affSColin FinckPUBLIC KiUserExceptionDispatcher 185c2c66affSColin Finck.PROC KiUserExceptionDispatcher 186c2c66affSColin Finck 187ff7035d9SHervé Poussineau /* The stack is set up with a KUSER_EXCEPTION_STACK */ 188ff7035d9SHervé Poussineau /* The frame ends with a MACHINE_FRAME. */ 1892a8c680dSTimo Kreuzer .PUSHFRAME 1902a8c680dSTimo Kreuzer 191ff7035d9SHervé Poussineau /* This is for the alignment, EXCEPTION_RECORD and CONTEXT */ 1922a8c680dSTimo Kreuzer .ALLOCSTACK 8 + EXCEPTION_RECORD_LENGTH + CONTEXT_FRAME_LENGTH 1932a8c680dSTimo Kreuzer .ENDPROLOG 1942a8c680dSTimo Kreuzer 1952a8c680dSTimo Kreuzer /* Clear direction flag */ 1962a8c680dSTimo Kreuzer cld 1972a8c680dSTimo Kreuzer 1982a8c680dSTimo Kreuzer /* Dispatch the exception */ 1992a8c680dSTimo Kreuzer call RtlDispatchException 2002a8c680dSTimo Kreuzer 2012a8c680dSTimo Kreuzer /* Check for success */ 2022a8c680dSTimo Kreuzer or al, al 2032a8c680dSTimo Kreuzer jz RaiseException 2042a8c680dSTimo Kreuzer 2052a8c680dSTimo Kreuzer /* We're fine, continue execution */ 206ff7035d9SHervé Poussineau lea rcx, [rsp] /* ContextRecord */ 207ff7035d9SHervé Poussineau mov dl, 0 /* TestAlert */ 2082a8c680dSTimo Kreuzer call ZwContinue 2092a8c680dSTimo Kreuzer 2102a8c680dSTimo Kreuzer /* Exit */ 2112a8c680dSTimo Kreuzer jmp Exit 2122a8c680dSTimo Kreuzer 2132a8c680dSTimo KreuzerRaiseException: 2142a8c680dSTimo Kreuzer 2152a8c680dSTimo Kreuzer /* Raise the exception */ 216ff7035d9SHervé Poussineau lea rcx, [rsp + CONTEXT_FRAME_LENGTH] /* ExceptionRecord */ 217ff7035d9SHervé Poussineau lea rdx, [rsp] /* ContextRecord */ 2182a8c680dSTimo Kreuzer xor r8, r8 2192a8c680dSTimo Kreuzer call ZwRaiseException 2202a8c680dSTimo Kreuzer 2212a8c680dSTimo KreuzerExit: 222ff7035d9SHervé Poussineau lea rcx, [rsp + CONTEXT_FRAME_LENGTH] /* ExceptionRecord */ 2232a8c680dSTimo Kreuzer mov rdx, rax 2242a8c680dSTimo Kreuzer call KiUserExceptionDispatcherNested 2252a8c680dSTimo Kreuzer ret 2262a8c680dSTimo Kreuzer 2272a8c680dSTimo Kreuzer.ENDP 2282a8c680dSTimo Kreuzer 2292a8c680dSTimo Kreuzer/* 2302a8c680dSTimo Kreuzer VOID 2312a8c680dSTimo Kreuzer KiUserExceptionDispatcherNested( 2322a8c680dSTimo Kreuzer _In_ ExceptionRecord<rcx>, 2332a8c680dSTimo Kreuzer _In_ Status<edx> 2342a8c680dSTimo Kreuzer ) 2352a8c680dSTimo Kreuzer */ 2362a8c680dSTimo Kreuzer.PROC KiUserExceptionDispatcherNested 2372a8c680dSTimo Kreuzer /* Allocate space for the nested exception record */ 2382a8c680dSTimo Kreuzer sub rsp, EXCEPTION_RECORD_LENGTH 2392a8c680dSTimo Kreuzer .ALLOCSTACK EXCEPTION_RECORD_LENGTH 2402a8c680dSTimo Kreuzer .ENDPROLOG 2412a8c680dSTimo Kreuzer 2422a8c680dSTimo Kreuzer /* Set it up */ 2432a8c680dSTimo Kreuzer mov dword ptr [rsp + ErNumberParameters], 0 2442a8c680dSTimo Kreuzer mov dword ptr [rsp + ErExceptionFlags], EXCEPTION_NONCONTINUABLE 2452a8c680dSTimo Kreuzer mov [rsp + ErExceptionRecord], rcx 2462a8c680dSTimo Kreuzer mov [rsp + ErExceptionCode], edx 2472a8c680dSTimo Kreuzer 2482a8c680dSTimo Kreuzer /* Raise the exception */ 2492a8c680dSTimo Kreuzer mov rcx, rsp 2502a8c680dSTimo Kreuzer call RtlRaiseException 2512a8c680dSTimo Kreuzer 2522a8c680dSTimo Kreuzer /* Cleanup stack and return */ 2532a8c680dSTimo Kreuzer add rsp, EXCEPTION_RECORD_LENGTH 2542a8c680dSTimo Kreuzer ret 255c2c66affSColin Finck.ENDP 256c2c66affSColin Finck 257c2c66affSColin FinckEND 258c2c66affSColin Finck 259