xref: /reactos/dll/ntdll/dispatch/amd64/dispatch.S (revision 29721ac5)
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