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