xref: /reactos/ntoskrnl/ke/amd64/usercall_asm.S (revision 34576c70)
1ff7035d9SHervé Poussineau/*
2ff7035d9SHervé Poussineau * PROJECT:     ReactOS Kernel
3ff7035d9SHervé Poussineau * LICENSE:     GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4ff7035d9SHervé Poussineau * PURPOSE:     ReactOS AMD64 user mode callback helper
5ff7035d9SHervé Poussineau * COPYRIGHT:   Timo Kreuzer (timo.kreuzer@reactos.org)
6ff7035d9SHervé Poussineau */
7fdc1261fSTimo Kreuzer
8fdc1261fSTimo Kreuzer#include <ksamd64.inc>
9*34576c70STimo Kreuzer#include <trapamd64.inc>
10*34576c70STimo Kreuzer
11*34576c70STimo KreuzerEXTERN KiInitiateUserApc:PROC
12*34576c70STimo KreuzerEXTERN KeUserCallbackDispatcher:QWORD
13fdc1261fSTimo Kreuzer
14ff7035d9SHervé Poussineau/*
15ff7035d9SHervé Poussineau * NTSTATUS
16ff7035d9SHervé Poussineau * KiUserModeCallout (
17ff7035d9SHervé Poussineau *     _Inout_ PKCALLOUT_FRAME CalloutFrame);
18ff7035d9SHervé Poussineau */
19fdc1261fSTimo KreuzerEXTERN KiUserModeCallout:PROC
20fdc1261fSTimo Kreuzer
21fdc1261fSTimo Kreuzer.code64
22fdc1261fSTimo Kreuzer
23ff7035d9SHervé Poussineau/*
24ff7035d9SHervé Poussineau * NTSTATUS
25ff7035d9SHervé Poussineau * KiCallUserMode (
26ff7035d9SHervé Poussineau *     _In_ PVOID *OutputBuffer@<rcx>,
27ff7035d9SHervé Poussineau *     _In_ PULONG OutputLength@<rdx>);
28ff7035d9SHervé Poussineau */
29fdc1261fSTimo KreuzerPUBLIC KiCallUserMode
30fdc1261fSTimo Kreuzer.PROC KiCallUserMode
31fdc1261fSTimo Kreuzer
32ff7035d9SHervé Poussineau    /* Generate a KEXCEPTION_FRAME on the stack */
33ff7035d9SHervé Poussineau    /* This is identical to a KCALLOUT_FRAME */
34fdc1261fSTimo Kreuzer    GENERATE_EXCEPTION_FRAME
35fdc1261fSTimo Kreuzer
36ff7035d9SHervé Poussineau    /* Save OutputBuffer and OutputLength */
37fdc1261fSTimo Kreuzer    mov [rsp + ExOutputBuffer], rcx
38fdc1261fSTimo Kreuzer    mov [rsp + ExOutputLength], rdx
39fdc1261fSTimo Kreuzer
40ff7035d9SHervé Poussineau    /* Call the C function */
41fdc1261fSTimo Kreuzer    mov rcx, rsp
42fdc1261fSTimo Kreuzer    call KiUserModeCallout
43fdc1261fSTimo Kreuzer
44ff7035d9SHervé Poussineau    /* Restore the registers from the KEXCEPTION_FRAME */
45fdc1261fSTimo Kreuzer    RESTORE_EXCEPTION_STATE
46fdc1261fSTimo Kreuzer
47ff7035d9SHervé Poussineau    /* Return */
48fdc1261fSTimo Kreuzer    ret
49fdc1261fSTimo Kreuzer
50fdc1261fSTimo Kreuzer.ENDP
51fdc1261fSTimo Kreuzer
52*34576c70STimo Kreuzer
53*34576c70STimo Kreuzer/*!
54*34576c70STimo Kreuzer * \brief Exits to user mode, restores only rsp and rip, zeroes the rest.
55*34576c70STimo Kreuzer *
56*34576c70STimo Kreuzer * \todo Merge this with KiCallUserMode + KiUserModeCallout and skip the trap frame.
57*34576c70STimo Kreuzer *
58*34576c70STimo Kreuzer * DECLSPEC_NORETURN
59*34576c70STimo Kreuzer * VOID
60*34576c70STimo Kreuzer * KiUserCallbackExit(
61*34576c70STimo Kreuzer *     _In_ PKTRAP_FRAME TrapFrame@<rcx>);
62*34576c70STimo Kreuzer */
63*34576c70STimo Kreuzer PUBLIC KiUserCallbackExit
64*34576c70STimo KreuzerKiUserCallbackExit:
65*34576c70STimo Kreuzer
66*34576c70STimo Kreuzer    /* Point rsp to the trap frame */
67*34576c70STimo Kreuzer    mov rsp, rcx
68*34576c70STimo Kreuzer
69*34576c70STimo Kreuzer    /* Zero non-volatile registers for KiUserCallbackDispatcher.
70*34576c70STimo Kreuzer       This must be done before dispatching a pending user APC. */
71*34576c70STimo Kreuzer    xor rbx, rbx
72*34576c70STimo Kreuzer    xor rdi, rdi
73*34576c70STimo Kreuzer    xor rsi, rsi
74*34576c70STimo Kreuzer    xor rbp, rbp
75*34576c70STimo Kreuzer    xor r12, r12
76*34576c70STimo Kreuzer    xor r13, r13
77*34576c70STimo Kreuzer    xor r14, r14
78*34576c70STimo Kreuzer    xor r15, r15
79*34576c70STimo Kreuzer    pxor xmm6, xmm6
80*34576c70STimo Kreuzer    pxor xmm7, xmm7
81*34576c70STimo Kreuzer    pxor xmm8, xmm8
82*34576c70STimo Kreuzer    pxor xmm9, xmm9
83*34576c70STimo Kreuzer    pxor xmm10, xmm10
84*34576c70STimo Kreuzer    pxor xmm11, xmm11
85*34576c70STimo Kreuzer    pxor xmm12, xmm12
86*34576c70STimo Kreuzer    pxor xmm13, xmm13
87*34576c70STimo Kreuzer    pxor xmm14, xmm14
88*34576c70STimo Kreuzer    pxor xmm15, xmm15
89*34576c70STimo Kreuzer
90*34576c70STimo Kreuzer    /* Check for pending user APC */
91*34576c70STimo Kreuzer    mov rdx, gs:[PcCurrentThread]
92*34576c70STimo Kreuzer    HANDLE_USER_APCS rdx, rsp
93*34576c70STimo Kreuzer
94*34576c70STimo Kreuzer    /* Zero volatile registers */
95*34576c70STimo Kreuzer    xor rax, rax
96*34576c70STimo Kreuzer    xor rdx, rdx
97*34576c70STimo Kreuzer    xor r8, r8
98*34576c70STimo Kreuzer    xor r9, r9
99*34576c70STimo Kreuzer    xor r10, r10
100*34576c70STimo Kreuzer    pxor xmm0, xmm0
101*34576c70STimo Kreuzer    pxor xmm1, xmm1
102*34576c70STimo Kreuzer    pxor xmm2, xmm2
103*34576c70STimo Kreuzer    pxor xmm3, xmm3
104*34576c70STimo Kreuzer    pxor xmm4, xmm4
105*34576c70STimo Kreuzer    pxor xmm5, xmm5
106*34576c70STimo Kreuzer
107*34576c70STimo Kreuzer    /* Disable interrupts for return */
108*34576c70STimo Kreuzer    cli
109*34576c70STimo Kreuzer
110*34576c70STimo Kreuzer    /* Prepare user mode return address (rcx) and eflags (r11) for sysret */
111*34576c70STimo Kreuzer    mov rcx, qword ptr KeUserCallbackDispatcher[rip]
112*34576c70STimo Kreuzer    mov r11, EFLAGS_IF_MASK
113*34576c70STimo Kreuzer
114*34576c70STimo Kreuzer    /* Load user mode stack (It was copied to the trap frame) */
115*34576c70STimo Kreuzer    mov rsp, [rsp + KTRAP_FRAME_Rsp]
116*34576c70STimo Kreuzer
117*34576c70STimo Kreuzer    /* Swap gs back to user */
118*34576c70STimo Kreuzer    swapgs
119*34576c70STimo Kreuzer
120*34576c70STimo Kreuzer    /* return to user mode */
121*34576c70STimo Kreuzer    sysretq
122*34576c70STimo Kreuzer
123*34576c70STimo Kreuzer
124ff7035d9SHervé Poussineau/*
125ff7035d9SHervé Poussineau * DECLSPEC_NORETURN
126ff7035d9SHervé Poussineau * VOID
127ff7035d9SHervé Poussineau * KiCallbackReturn (
128ff7035d9SHervé Poussineau *     _In_ PVOID Stack,
129ff7035d9SHervé Poussineau *     _In_ NTSTATUS Status);
130ff7035d9SHervé Poussineau */
131fdc1261fSTimo KreuzerPUBLIC KiCallbackReturn
132fdc1261fSTimo Kreuzer.PROC KiCallbackReturn
133fdc1261fSTimo Kreuzer
134fdc1261fSTimo Kreuzer    .ENDPROLOG
135fdc1261fSTimo Kreuzer
136ff7035d9SHervé Poussineau    /* Restore the stack */
137fdc1261fSTimo Kreuzer    mov rsp, rcx
138fdc1261fSTimo Kreuzer
139ff7035d9SHervé Poussineau    /* Set return status */
140fdc1261fSTimo Kreuzer    mov eax, edx
141fdc1261fSTimo Kreuzer
142ff7035d9SHervé Poussineau    /* Restore the registers from the KEXCEPTION_FRAME */
143fdc1261fSTimo Kreuzer    RESTORE_EXCEPTION_STATE
144fdc1261fSTimo Kreuzer
145ff7035d9SHervé Poussineau    /* Return */
146fdc1261fSTimo Kreuzer    ret
147fdc1261fSTimo Kreuzer
148fdc1261fSTimo Kreuzer.ENDP
149fdc1261fSTimo Kreuzer
150fdc1261fSTimo Kreuzer
151fdc1261fSTimo KreuzerEND
152