1/*
2 * PROJECT:     ReactOS api tests
3 * LICENSE:     GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4 * PURPOSE:     Test helper for x64 RtlCaptureContext
5 * COPYRIGHT:   Copyright 2022 Timo Kreuzer <timo.kreuzer@reactos.org>
6 */
7
8#include <asm.inc>
9#include <ksamd64.inc>
10
11.code64
12
13EXTERN RtlCaptureContext:PROC
14
15FUNC ZeroContext
16
17    pushfq
18    .ALLOCSTACK 8
19    push rax
20    .PUSHREG rax
21    push rcx
22    .PUSHREG rcx
23    push rdi
24    .PUSHREG rdi
25    .ENDPROLOG
26
27    mov rdi, rcx
28    mov rcx, CONTEXT_FRAME_LENGTH
29    xor eax, eax
30    cld
31    rep stosb
32
33    pop rdi
34    pop rcx
35    pop rax
36    popfq
37    ret
38
39ENDFUNC
40
41//
42// VOID
43// RtlCaptureContextWrapper (
44//    _Inout_ PCONTEXT InOutContext,
45//    _Out_ PCONTEXT CapturedContext);
46//
47PUBLIC RtlCaptureContextWrapper
48FUNC RtlCaptureContextWrapper
49
50    // Generate a KEXCEPTION_FRAME on the stack
51    GENERATE_EXCEPTION_FRAME
52
53    // Save parameters
54    mov [rsp + ExP1Home], rcx
55    mov [rsp + ExP2Home], rdx
56
57    // Save current EFlags
58    pushfq
59    pop qword ptr [rsp + ExP3Home]
60
61    // Load integer registers from InOutContext
62    mov rax, [rcx + CxRax]
63    mov rdx, [rcx + CxRdx]
64    mov rbx, [rcx + CxRbx]
65    mov rbp, [rcx + CxRbp]
66    mov rsi, [rcx + CxRsi]
67    mov rdi, [rcx + CxRdi]
68    mov r8, [rcx + CxR8]
69    mov r9, [rcx + CxR9]
70    mov r10, [rcx + CxR10]
71    mov r11, [rcx + CxR11]
72    mov r12, [rcx + CxR12]
73    mov r13, [rcx + CxR13]
74    mov r14, [rcx + CxR14]
75    mov r15, [rcx + CxR15]
76
77    // Load floating point registers from InOutContext
78    fxrstor [rcx + CxFltSave]
79
80    // Load MxCsr (this overwrites the value from FltSave)
81    ldmxcsr [rcx + CxMxCsr]
82
83    // Load XMM registers
84    movaps xmm0, [rcx + CxXmm0]
85    movaps xmm1, [rcx + CxXmm1]
86    movaps xmm2, [rcx + CxXmm2]
87    movaps xmm3, [rcx + CxXmm3]
88    movaps xmm4, [rcx + CxXmm4]
89    movaps xmm5, [rcx + CxXmm5]
90    movaps xmm6, [rcx + CxXmm6]
91    movaps xmm7, [rcx + CxXmm7]
92    movaps xmm8, [rcx + CxXmm8]
93    movaps xmm9, [rcx + CxXmm9]
94    movaps xmm10, [rcx + CxXmm10]
95    movaps xmm11, [rcx + CxXmm11]
96    movaps xmm12, [rcx + CxXmm12]
97    movaps xmm13, [rcx + CxXmm13]
98    movaps xmm14, [rcx + CxXmm14]
99    movaps xmm15, [rcx + CxXmm15]
100
101    // Load EFlags
102    push qword ptr [rcx + CxEFlags]
103    popfq
104
105    // Capture the context
106    mov rcx, [rsp + ExP2Home]
107    call RtlCaptureContext
108ReturnAddress:
109
110    // Save the returned rcx
111    mov [rsp + ExP4Home], rcx
112
113    // Restore original rcx
114    mov rcx, [rsp + ExP1Home]
115
116    // Zero out the context (this does not clobber any registers/flags)
117    call ZeroContext
118
119    // Save returned Eflags
120    pushfq
121    pop qword ptr [rcx + CxEFlags]
122
123    // Restore original EFLags
124    push qword ptr [rsp + ExP3Home]
125    popfq
126
127    // Save returned integer registers to InOutContext
128    mov [rcx + CxRax], rax
129    mov [rcx + CxRdx], rdx
130    mov [rcx + CxRbx], rbx
131    mov [rcx + CxRbp], rbp
132    mov [rcx + CxRsi], rsi
133    mov [rcx + CxRdi], rdi
134    mov [rcx + CxR8], r8
135    mov [rcx + CxR9], r9
136    mov [rcx + CxR10], r10
137    mov [rcx + CxR11], r11
138    mov [rcx + CxR12], r12
139    mov [rcx + CxR13], r13
140    mov [rcx + CxR14], r14
141    mov [rcx + CxR15], r15
142
143    // Save the returned rcx in the context
144    mov rax, [rsp + ExP4Home]
145    mov [rcx + CxRcx], rax
146
147    // Save returned floating point registers to InOutContext
148    stmxcsr [rcx + CxMxCsr]
149    fxsave [rcx + CxFltSave]
150    movaps [rcx + CxXmm0], xmm0
151    movaps [rcx + CxXmm1], xmm1
152    movaps [rcx + CxXmm2], xmm2
153    movaps [rcx + CxXmm3], xmm3
154    movaps [rcx + CxXmm4], xmm4
155    movaps [rcx + CxXmm5], xmm5
156    movaps [rcx + CxXmm6], xmm6
157    movaps [rcx + CxXmm7], xmm7
158    movaps [rcx + CxXmm8], xmm8
159    movaps [rcx + CxXmm9], xmm9
160    movaps [rcx + CxXmm10], xmm10
161    movaps [rcx + CxXmm11], xmm11
162    movaps [rcx + CxXmm12], xmm12
163    movaps [rcx + CxXmm13], xmm13
164    movaps [rcx + CxXmm14], xmm14
165    movaps [rcx + CxXmm15], xmm15
166
167    // Save the expected return address
168    lea rax, ReturnAddress[rip]
169    mov [rcx + CxRip], rax
170
171    // Save the expected stored rsp
172    mov [rcx + CxRsp], rsp
173
174    // Restore the registers from the KEXCEPTION_FRAME
175    RESTORE_EXCEPTION_STATE
176
177    ret
178
179ENDFUNC
180
181
182END
183