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