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