1/* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS kernel 4 * FILE: ntdll/dispatch/amd64/dispatch.S 5 * PURPOSE: Usermode dispatcher stubs 6 * 7 * PROGRAMMER: Timo kreuzer (timo.kreuzer@reactos.org) 8 */ 9 10/* INCLUDES ******************************************************************/ 11 12#include <asm.inc> 13#include <ksamd64.inc> 14 15EXTERN NtContinue:PROC 16EXTERN LdrpInit:PROC 17EXTERN ZwCallbackReturn:PROC 18EXTERN RtlRaiseStatus:PROC 19 20.code 21 22PUBLIC LdrInitializeThunk 23.PROC LdrInitializeThunk 24 mov rbp, 0 25 .setframe rbp, 0 26 .endprolog 27 28 /* First parameter is the APC context */ 29 mov rcx, r9 30 jmp LdrpInit 31 32.ENDP 33 34PUBLIC KiUserApcDispatcher 35.PROC KiUserApcDispatcher 36 37 /* The stack is set up with a UAPC_FRAME, which ends with a MACHINE_FRAME */ 38 .PUSHFRAME 39 .ALLOCSTACK CONTEXT_FRAME_LENGTH 40 41 /* The stack points to a CONTEXT structure. 42 Create unwind ops for all nonvolatile registers */ 43 .SAVEREG rbx, CxRbx 44 .SAVEREG rbp, CxRbp 45 .SAVEREG rsi, CxRsi 46 .SAVEREG rdi, CxRdi 47 .SAVEREG r12, CxR12 48 .SAVEREG r13, CxR13 49 .SAVEREG r14, CxR14 50 .SAVEREG r15, CxR15 51 .SAVEXMM128 xmm6, CxXmm6 52 .SAVEXMM128 xmm7, CxXmm7 53 .SAVEXMM128 xmm8, CxXmm8 54 .SAVEXMM128 xmm9, CxXmm9 55 .SAVEXMM128 xmm10, CxXmm10 56 .SAVEXMM128 xmm11, CxXmm11 57 .SAVEXMM128 xmm12, CxXmm12 58 .SAVEXMM128 xmm13, CxXmm13 59 .SAVEXMM128 xmm14, CxXmm14 60 .SAVEXMM128 xmm15, CxXmm15 61 62 .endprolog 63 /* We enter with a 16 byte aligned stack */ 64 65 mov rcx, [rsp + CONTEXT_P1Home] /* NormalContext */ 66 mov rdx, [rsp + CONTEXT_P2Home] /* SystemArgument1 */ 67 mov r8, [rsp + CONTEXT_P3Home] /* SystemArgument2 */ 68 lea r9, [rsp] /* Context */ 69 call qword ptr [rsp + CONTEXT_P4Home] /* NormalRoutine */ 70 71 /* NtContinue(Context, TRUE); */ 72 lea rcx, [rsp] 73 mov dl, 1 74 call NtContinue 75 76 nop 77 int 3 78.ENDP 79 80 81PUBLIC KiRaiseUserExceptionDispatcher 82.PROC KiRaiseUserExceptionDispatcher 83 .endprolog 84 int 3 85 86.ENDP 87 88PUBLIC KiUserCallbackDispatcher 89.PROC KiUserCallbackDispatcher 90 91 /* The stack is set up with a UCALLOUT_FRAME */ 92 /* The frame ends with a MACHINE_FRAME. */ 93 .PUSHFRAME 94 95 /* This is for the Home space, Buffer, Length and ApiNumber */ 96 .ALLOCSTACK (6 * 8) 97 .ENDPROLOG 98 99#if DBG 100 /* We enter the function with a fully setup stack, so it must be aligned! */ 101 test rsp, 15 102 jz AlignmentOk 103 int HEX(2C) 104AlignmentOk: 105#endif 106 107 /* Get the parameters from the callout frame */ 108 mov rcx, [rsp + CkBuffer] 109 mov edx, [rsp + CkLength] 110 mov r8d, [rsp + CkApiNumber] 111 112 /* Get the callback table */ 113 mov rax, gs:[TePeb] 114 mov r9, [rax + PeKernelCallbackTable] 115 116 /* Call the routine */ 117 call qword ptr [r9 + r8 * 8] 118 119 /* Return from callback */ 120 xor ecx, ecx 121 xor edx, edx 122 mov r8d, eax 123 call ZwCallbackReturn 124 125 /* Save callback return value */ 126 mov esi, eax 127 128 /* Raise status */ 129StatusRaise: 130 mov ecx, esi 131 call RtlRaiseStatus 132 jmp StatusRaise 133 134.ENDP 135 136/* 137 BOOLEAN 138 NTAPI 139 RtlDispatchException( 140 _In_ PEXCEPTION_RECORD ExceptionRecord, 141 _In_ PCONTEXT ContextRecord); 142 */ 143EXTERN RtlDispatchException:PROC 144 145/* 146 NTSTATUS 147 NTAPI 148 ZwContinue( 149 _In_ PCONTEXT Context, 150 _In_ BOOLEAN TestAlert); 151 */ 152EXTERN ZwContinue:PROC 153 154/* 155 NTSTATUS 156 NTAPI 157 ZwRaiseException( 158 _In_ PEXCEPTION_RECORD ExceptionRecord, 159 _In_ PCONTEXT Context, 160 _In_ BOOLEAN SearchFrames); 161 */ 162EXTERN ZwRaiseException:PROC 163 164/* 165 VOID 166 NTAPI 167 RtlRaiseStatus( 168 _In_ PEXCEPTION_RECORD ExceptionRecord); 169 */ 170EXTERN RtlRaiseException:PROC 171 172/* 173 VOID 174 KiUserExceptionDispatcher( 175 CONTEXT ContextRecord<rcx>, 176 PEXCEPTION_RECORD ExceptionRecord<rdx>); 177 178 This function is called with the following stack layout: 179 CONTEXT ContextRecord <- RSP, RCX 180 EXCEPTION_RECORD ExceptionRecord <- RDX 181 ULONG64 Alignment 182 MACHINE_FRAME MachineFrame 183 */ 184PUBLIC KiUserExceptionDispatcher 185.PROC KiUserExceptionDispatcher 186 187 /* The stack is set up with a KUSER_EXCEPTION_STACK */ 188 /* The frame ends with a MACHINE_FRAME. */ 189 .PUSHFRAME 190 191 /* This is for the alignment, EXCEPTION_RECORD and CONTEXT */ 192 .ALLOCSTACK 8 + EXCEPTION_RECORD_LENGTH + CONTEXT_FRAME_LENGTH 193 .ENDPROLOG 194 195 /* Clear direction flag */ 196 cld 197 198 /* Dispatch the exception */ 199 call RtlDispatchException 200 201 /* Check for success */ 202 or al, al 203 jz RaiseException 204 205 /* We're fine, continue execution */ 206 lea rcx, [rsp] /* ContextRecord */ 207 mov dl, 0 /* TestAlert */ 208 call ZwContinue 209 210 /* Exit */ 211 jmp Exit 212 213RaiseException: 214 215 /* Raise the exception */ 216 lea rcx, [rsp + CONTEXT_FRAME_LENGTH] /* ExceptionRecord */ 217 lea rdx, [rsp] /* ContextRecord */ 218 xor r8, r8 219 call ZwRaiseException 220 221Exit: 222 lea rcx, [rsp + CONTEXT_FRAME_LENGTH] /* ExceptionRecord */ 223 mov rdx, rax 224 call KiUserExceptionDispatcherNested 225 ret 226 227.ENDP 228 229/* 230 VOID 231 KiUserExceptionDispatcherNested( 232 _In_ ExceptionRecord<rcx>, 233 _In_ Status<edx> 234 ) 235 */ 236.PROC KiUserExceptionDispatcherNested 237 /* Allocate space for the nested exception record */ 238 sub rsp, EXCEPTION_RECORD_LENGTH 239 .ALLOCSTACK EXCEPTION_RECORD_LENGTH 240 .ENDPROLOG 241 242 /* Set it up */ 243 mov dword ptr [rsp + ErNumberParameters], 0 244 mov dword ptr [rsp + ErExceptionFlags], EXCEPTION_NONCONTINUABLE 245 mov [rsp + ErExceptionRecord], rcx 246 mov [rsp + ErExceptionCode], edx 247 248 /* Raise the exception */ 249 mov rcx, rsp 250 call RtlRaiseException 251 252 /* Cleanup stack and return */ 253 add rsp, EXCEPTION_RECORD_LENGTH 254 ret 255.ENDP 256 257END 258 259