xref: /reactos/ntoskrnl/ke/amd64/context.c (revision 07608028)
1 /*
2  * PROJECT:         ReactOS Kernel
3  * LICENSE:         GPL - See COPYING in the top level directory
4  * PURPOSE:         CONTEXT related functions
5  * PROGRAMMERS:     Timo Kreuzer (timo.kreuzer@reactos.org)
6  */
7 
8 /* INCLUDES ******************************************************************/
9 
10 #include <ntoskrnl.h>
11 
12 #define NDEBUG
13 #include <debug.h>
14 
15 /* FUNCTIONS *****************************************************************/
16 
17 VOID
18 NTAPI
19 KeContextToTrapFrame(IN PCONTEXT Context,
20                      IN OUT PKEXCEPTION_FRAME ExceptionFrame,
21                      IN OUT PKTRAP_FRAME TrapFrame,
22                      IN ULONG ContextFlags,
23                      IN KPROCESSOR_MODE PreviousMode)
24 {
25     KIRQL OldIrql;
26 
27     /* Make sure we have an amd64 context, then remove the flag */
28     ASSERT(ContextFlags & CONTEXT_AMD64);
29     ContextFlags &= ~CONTEXT_AMD64;
30 
31     /* Do this at APC_LEVEL */
32     OldIrql = KeGetCurrentIrql();
33     if (OldIrql < APC_LEVEL) KeRaiseIrql(APC_LEVEL, &OldIrql);
34 
35     /* Handle integer registers */
36     if (ContextFlags & CONTEXT_INTEGER)
37     {
38         TrapFrame->Rax = Context->Rax;
39         TrapFrame->Rbx = Context->Rbx;
40         TrapFrame->Rcx = Context->Rcx;
41         TrapFrame->Rdx = Context->Rdx;
42         TrapFrame->Rsi = Context->Rsi;
43         TrapFrame->Rdi = Context->Rdi;
44         TrapFrame->Rbp = Context->Rbp;
45         TrapFrame->R8 = Context->R8;
46         TrapFrame->R9 = Context->R9;
47         TrapFrame->R10 = Context->R10;
48         TrapFrame->R11 = Context->R11;
49         if (ExceptionFrame)
50         {
51             ExceptionFrame->R12 = Context->R12;
52             ExceptionFrame->R13 = Context->R13;
53             ExceptionFrame->R14 = Context->R14;
54             ExceptionFrame->R15 = Context->R15;
55         }
56     }
57 
58     /* Handle floating point registers */
59     if ((ContextFlags & CONTEXT_FLOATING_POINT) &&
60         ((Context->SegCs & MODE_MASK) != KernelMode))
61     {
62         TrapFrame->MxCsr = Context->MxCsr;
63         TrapFrame->Xmm0 = Context->Xmm0;
64         TrapFrame->Xmm1 = Context->Xmm1;
65         TrapFrame->Xmm2 = Context->Xmm2;
66         TrapFrame->Xmm3 = Context->Xmm3;
67         TrapFrame->Xmm4 = Context->Xmm4;
68         TrapFrame->Xmm5 = Context->Xmm5;
69         if (ExceptionFrame)
70         {
71             ExceptionFrame->Xmm6 = Context->Xmm6;
72             ExceptionFrame->Xmm7 = Context->Xmm7;
73             ExceptionFrame->Xmm8 = Context->Xmm8;
74             ExceptionFrame->Xmm9 = Context->Xmm9;
75             ExceptionFrame->Xmm10 = Context->Xmm10;
76             ExceptionFrame->Xmm11 = Context->Xmm11;
77             ExceptionFrame->Xmm12 = Context->Xmm12;
78             ExceptionFrame->Xmm13 = Context->Xmm13;
79             ExceptionFrame->Xmm14 = Context->Xmm14;
80             ExceptionFrame->Xmm15 = Context->Xmm15;
81         }
82     }
83 
84     /* Handle control registers */
85     if (ContextFlags & CONTEXT_CONTROL)
86     {
87         /* Check if this was a Kernel Trap */
88         if ((Context->SegCs & MODE_MASK) == KernelMode)
89         {
90             /* Set valid selectors */
91             TrapFrame->SegCs = KGDT64_R0_CODE;
92             TrapFrame->SegSs = KGDT64_R0_DATA;
93         }
94         else
95         {
96             /* Copy selectors */
97             TrapFrame->SegCs = Context->SegCs;
98             TrapFrame->SegSs = Context->SegSs;
99         }
100 
101         /* RIP, RSP, EFLAGS */
102         TrapFrame->Rip = Context->Rip;
103         TrapFrame->Rsp = Context->Rsp;
104         TrapFrame->EFlags = Context->EFlags;
105     }
106 
107     /* Handle segment selectors */
108     if (ContextFlags & CONTEXT_SEGMENTS)
109     {
110         /* Check if this was a Kernel Trap */
111         if ((Context->SegCs & MODE_MASK) == KernelMode)
112         {
113             /* Set valid selectors */
114             TrapFrame->SegDs = KGDT64_R3_DATA | RPL_MASK;
115             TrapFrame->SegEs = KGDT64_R3_DATA | RPL_MASK;
116             TrapFrame->SegFs = KGDT64_R3_CMTEB | RPL_MASK;
117             TrapFrame->SegGs = KGDT64_R3_DATA | RPL_MASK;
118         }
119         else
120         {
121             /* Copy selectors */
122             TrapFrame->SegDs = Context->SegDs;
123             TrapFrame->SegEs = Context->SegEs;
124             TrapFrame->SegFs = Context->SegFs;
125             TrapFrame->SegGs = Context->SegGs;
126         }
127     }
128 
129     /* Handle debug registers */
130     if (ContextFlags & CONTEXT_DEBUG_REGISTERS)
131     {
132         /* Copy the debug registers */
133         TrapFrame->Dr0 = Context->Dr0;
134         TrapFrame->Dr1 = Context->Dr1;
135         TrapFrame->Dr2 = Context->Dr2;
136         TrapFrame->Dr3 = Context->Dr3;
137         TrapFrame->Dr6 = Context->Dr6;
138         TrapFrame->Dr7 = Context->Dr7;
139     }
140 
141     /* Restore IRQL */
142     if (OldIrql < APC_LEVEL) KeLowerIrql(OldIrql);
143 }
144 
145 VOID
146 NTAPI
147 KeTrapFrameToContext(IN PKTRAP_FRAME TrapFrame,
148                      IN PKEXCEPTION_FRAME ExceptionFrame,
149                      IN OUT PCONTEXT Context)
150 {
151     ULONG ContextFlags;
152     KIRQL OldIrql;
153 
154     /* Do this at APC_LEVEL */
155     OldIrql = KeGetCurrentIrql();
156     if (OldIrql < APC_LEVEL) KeRaiseIrql(APC_LEVEL, &OldIrql);
157 
158     /* Make sure we have an amd64 context, then remove the flag */
159     ContextFlags = Context->ContextFlags;
160     ASSERT(ContextFlags & CONTEXT_AMD64);
161     ContextFlags &= ~CONTEXT_AMD64;
162 
163     /* Handle integer registers */
164     if (ContextFlags & CONTEXT_INTEGER)
165     {
166         Context->Rax = TrapFrame->Rax;
167         Context->Rbx = TrapFrame->Rbx;
168         Context->Rcx = TrapFrame->Rcx;
169         Context->Rdx = TrapFrame->Rdx;
170         Context->Rsi = TrapFrame->Rsi;
171         Context->Rdi = TrapFrame->Rdi;
172         Context->Rbp = TrapFrame->Rbp;
173         Context->R8 = TrapFrame->R8;
174         Context->R9 = TrapFrame->R9;
175         Context->R10 = TrapFrame->R10;
176         Context->R11 = TrapFrame->R11;
177 
178         if (ExceptionFrame)
179         {
180             Context->R12 = ExceptionFrame->R12;
181             Context->R13 = ExceptionFrame->R13;
182             Context->R14 = ExceptionFrame->R14;
183             Context->R15 = ExceptionFrame->R15;
184         }
185     }
186 
187     /* Handle floating point registers */
188     if ((ContextFlags & CONTEXT_FLOATING_POINT) &&
189         ((TrapFrame->SegCs & MODE_MASK) != KernelMode))
190     {
191         Context->Xmm0 = TrapFrame->Xmm0;
192         Context->Xmm1 = TrapFrame->Xmm1;
193         Context->Xmm2 = TrapFrame->Xmm2;
194         Context->Xmm3 = TrapFrame->Xmm3;
195         Context->Xmm4 = TrapFrame->Xmm4;
196         Context->Xmm5 = TrapFrame->Xmm5;
197         if (ExceptionFrame)
198         {
199             Context->Xmm6 = ExceptionFrame->Xmm6;
200             Context->Xmm7 = ExceptionFrame->Xmm7;
201             Context->Xmm8 = ExceptionFrame->Xmm8;
202             Context->Xmm9 = ExceptionFrame->Xmm9;
203             Context->Xmm10 = ExceptionFrame->Xmm10;
204             Context->Xmm11 = ExceptionFrame->Xmm11;
205             Context->Xmm12 = ExceptionFrame->Xmm12;
206             Context->Xmm13 = ExceptionFrame->Xmm13;
207             Context->Xmm14 = ExceptionFrame->Xmm14;
208             Context->Xmm15 = ExceptionFrame->Xmm15;
209         }
210     }
211 
212     /* Handle control registers */
213     if (ContextFlags & CONTEXT_CONTROL)
214     {
215         /* Check if this was a Kernel Trap */
216         if ((TrapFrame->SegCs & MODE_MASK) == KernelMode)
217         {
218             /* Set valid selectors */
219             Context->SegCs = KGDT64_R0_CODE;
220             Context->SegSs = KGDT64_R0_DATA;
221         }
222         else
223         {
224             /* Copy selectors */
225             Context->SegCs = TrapFrame->SegCs;
226             Context->SegSs = TrapFrame->SegSs;
227         }
228 
229         /* Copy RIP, RSP, EFLAGS */
230         Context->Rip = TrapFrame->Rip;
231         Context->Rsp = TrapFrame->Rsp;
232         Context->EFlags = TrapFrame->EFlags;
233     }
234 
235     /* Handle segment selectors */
236     if (ContextFlags & CONTEXT_SEGMENTS)
237     {
238         /* Check if this was a Kernel Trap */
239         if ((TrapFrame->SegCs & MODE_MASK) == KernelMode)
240         {
241             /* Set valid selectors */
242             Context->SegDs = KGDT64_R3_DATA | RPL_MASK;
243             Context->SegEs = KGDT64_R3_DATA | RPL_MASK;
244             Context->SegFs = KGDT64_R3_CMTEB | RPL_MASK;
245             Context->SegGs = KGDT64_R3_DATA | RPL_MASK;
246         }
247         else
248         {
249             /* Copy selectors */
250             Context->SegDs = TrapFrame->SegDs;
251             Context->SegEs = TrapFrame->SegEs;
252             Context->SegFs = TrapFrame->SegFs;
253             Context->SegGs = TrapFrame->SegGs;
254         }
255     }
256 
257     /* Handle debug registers */
258     if (ContextFlags & CONTEXT_DEBUG_REGISTERS)
259     {
260         /* Copy the debug registers */
261         Context->Dr0 = TrapFrame->Dr0;
262         Context->Dr1 = TrapFrame->Dr1;
263         Context->Dr2 = TrapFrame->Dr2;
264         Context->Dr3 = TrapFrame->Dr3;
265         Context->Dr6 = TrapFrame->Dr6;
266         Context->Dr7 = TrapFrame->Dr7;
267     }
268 
269     /* Restore IRQL */
270     if (OldIrql < APC_LEVEL) KeLowerIrql(OldIrql);
271 }
272 
273