[CONSRV]
[reactos.git] / include / asm / trapamd64.inc
1
2 APIC_EOI = HEX(0FFFFFFFFFFFE00B0)
3
4 TF_VOLATILES = HEX(01)
5 TF_NONVOLATILES = HEX(02)
6 TF_XMM = HEX(04)
7 TF_SEGMENTS = HEX(08)
8 TF_DEBUG = HEX(10)
9 TF_IRQL = HEX(20)
10 TF_SAVE_ALL = (TF_VOLATILES OR TF_NONVOLATILES OR TF_XMM OR TF_SEGMENTS)
11 TF_HAS_ERROR_CODE = HEX(40)
12 TF_SEND_EOI = HEX(80)
13 //TF_SYSTEMSERVICE = (TRAPFLAG_VOLATILES or TRAPFLAG_DEBUG)
14 TF_CHECKUSERAPC = HEX(100)
15
16 /*
17 * Stack Layout:
18 * |-------------------|
19 * | KTRAP_FRAME |
20 * |-------------------| <- rbp
21 * | EXCEPTION_RECORD |
22 * |-------------------|
23 * | KEXCEPTION_FRAME |
24 * |-------------------| <- rsp
25 *
26 */
27
28 /*
29 * EnterTrap - Allocate KTRAP_FRAME_LENGTH and save registers to it
30 */
31 MACRO(EnterTrap, Flags)
32 LOCAL kernel_mode_entry
33
34 /* Save the trap flags for this trap */
35 CurrentTrapFlags = VAL(Flags)
36
37 /* Size of hardware trap frame */
38 if (Flags AND TF_HAS_ERROR_CODE)
39 .pushframe code
40 SIZE_INITIAL_FRAME = 6 * 8
41 else
42 .pushframe
43 SIZE_INITIAL_FRAME = 5 * 8
44 endif
45
46 /* Make room for a KTRAP_FRAME */
47 sub rsp, (KTRAP_FRAME_LENGTH - SIZE_INITIAL_FRAME)
48 .allocstack (KTRAP_FRAME_LENGTH - SIZE_INITIAL_FRAME)
49
50 /* Save rbp and rax */
51 mov [rsp + KTRAP_FRAME_Rbp], rbp
52 .savereg rbp, KTRAP_FRAME_Rbp
53 mov [rsp + KTRAP_FRAME_Rax], rax
54 .savereg rax, KTRAP_FRAME_Rax
55
56 /* Point rbp to the KTRAP_FRAME */
57 lea rbp, [rsp]
58 .setframe rbp, 0
59
60 if (Flags AND TF_NONVOLATILES)
61 /* Save non-volatile registers */
62 mov [rbp + KTRAP_FRAME_Rbx], rbx
63 .savereg rbx, KTRAP_FRAME_Rbx
64 mov [rbp + KTRAP_FRAME_Rdi], rdi
65 .savereg rdi, KTRAP_FRAME_Rdi
66 mov [rbp + KTRAP_FRAME_Rsi], rsi
67 .savereg rsi, KTRAP_FRAME_Rsi
68 endif
69
70 .endprolog
71
72 if (Flags AND TF_VOLATILES)
73 /* Save volatile registers */
74 mov [rbp + KTRAP_FRAME_Rcx], rcx
75 mov [rbp + KTRAP_FRAME_Rdx], rdx
76 mov [rbp + KTRAP_FRAME_R8], r8
77 mov [rbp + KTRAP_FRAME_R9], r9
78 mov [rbp + KTRAP_FRAME_R10], r10
79 mov [rbp + KTRAP_FRAME_R11], r11
80 endif
81
82 if (Flags AND TF_XMM)
83 /* Save xmm registers */
84 movdqa [rbp + KTRAP_FRAME_Xmm0], xmm0
85 movdqa [rbp + KTRAP_FRAME_Xmm1], xmm1
86 movdqa [rbp + KTRAP_FRAME_Xmm2], xmm2
87 movdqa [rbp + KTRAP_FRAME_Xmm3], xmm3
88 movdqa [rbp + KTRAP_FRAME_Xmm4], xmm4
89 movdqa [rbp + KTRAP_FRAME_Xmm5], xmm5
90 endif
91
92 if (Flags AND TF_SEGMENTS)
93 /* Save segment selectors */
94 mov [rbp + KTRAP_FRAME_SegDs], ds
95 mov [rbp + KTRAP_FRAME_SegEs], es
96 mov [rbp + KTRAP_FRAME_SegFs], fs
97 mov [rbp + KTRAP_FRAME_SegGs], gs
98 endif
99
100 /* Save previous mode and check if it was user mode */
101 mov ax, [rbp + KTRAP_FRAME_SegCs]
102 and al, 1
103 mov [rbp + KTRAP_FRAME_PreviousMode], al
104 jz kernel_mode_entry
105
106 /* Set sane segments */
107 mov ax, (KGDT64_R3_DATA or RPL_MASK)
108 mov ds, ax
109 mov es, ax
110 swapgs
111
112 kernel_mode_entry:
113
114 // if (Flags AND TF_IRQL)
115 /* Save previous irql */
116 mov rax, cr8
117 mov [rbp + KTRAP_FRAME_PreviousIrql], al
118 // endif
119
120 if (Flags AND TF_DEBUG)
121 /* Save debug registers */
122 mov rax, dr0
123 mov [rbp + KTRAP_FRAME_Dr0], rax
124 mov rax, dr1
125 mov [rbp + KTRAP_FRAME_Dr1], rax
126 mov rax, dr2
127 mov [rbp + KTRAP_FRAME_Dr2], rax
128 mov rax, dr3
129 mov [rbp + KTRAP_FRAME_Dr3], rax
130 mov rax, dr6
131 mov [rbp + KTRAP_FRAME_Dr6], rax
132 mov rax, dr7
133 mov [rbp + KTRAP_FRAME_Dr7], rax
134 endif
135
136 /* Make sure the direction flag is cleared */
137 cld
138 ENDM
139
140 /*
141 * ExitTrap - Restore registers and free stack space
142 */
143 MACRO(ExitTrap, Flags)
144 LOCAL kernel_mode_return
145
146 #if DBG
147 /* Check previous irql */
148 mov rax, cr8
149 cmp [rbp + KTRAP_FRAME_PreviousIrql], al
150 je .irql_ok
151 int 3
152 .irql_ok:
153 #endif
154
155 if (Flags AND TF_SEGMENTS)
156 /* Restore segment selectors */
157 mov ds, [rbp + KTRAP_FRAME_SegDs]
158 mov es, [rbp + KTRAP_FRAME_SegEs]
159 mov fs, [rbp + KTRAP_FRAME_SegFs]
160 endif
161
162 if (Flags AND TF_IRQL)
163 /* Restore previous irql */
164 movzx rax, byte ptr [rbp + KTRAP_FRAME_PreviousIrql]
165 mov cr8, rax
166 endif
167
168 /* Check if we came from user mode */
169 test byte ptr [rbp + KTRAP_FRAME_SegCs], 1
170 jz kernel_mode_return
171
172 if (Flags AND TF_CHECKUSERAPC)
173 /* Load current thread into r10 */
174 mov r10, gs:[PcCurrentThread]
175 cmp byte ptr [r10 + KTHREAD_UserApcPending], 0
176 jne KiExitToUserApc
177
178 endif
179
180 /* Swap gs to user mode */
181 swapgs
182
183 kernel_mode_return:
184
185 if (Flags AND TF_NONVOLATILES)
186 /* Restore non-volatile registers */
187 mov rbx, [rbp + KTRAP_FRAME_Rbx]
188 mov rdi, [rbp + KTRAP_FRAME_Rdi]
189 mov rsi, [rbp + KTRAP_FRAME_Rsi]
190 endif
191
192 if (Flags AND TF_VOLATILES)
193 /* Restore volatile registers */
194 mov rax, [rbp + KTRAP_FRAME_Rax]
195 mov rcx, [rbp + KTRAP_FRAME_Rcx]
196 mov rdx, [rbp + KTRAP_FRAME_Rdx]
197 mov r8, [rbp + KTRAP_FRAME_R8]
198 mov r9, [rbp + KTRAP_FRAME_R9]
199 mov r10, [rbp + KTRAP_FRAME_R10]
200 mov r11, [rbp + KTRAP_FRAME_R11]
201 endif
202
203 if (Flags AND TF_XMM)
204 /* Restore xmm registers */
205 movdqa xmm0, [rbp + KTRAP_FRAME_Xmm0]
206 movdqa xmm1, [rbp + KTRAP_FRAME_Xmm1]
207 movdqa xmm2, [rbp + KTRAP_FRAME_Xmm2]
208 movdqa xmm3, [rbp + KTRAP_FRAME_Xmm3]
209 movdqa xmm4, [rbp + KTRAP_FRAME_Xmm4]
210 movdqa xmm5, [rbp + KTRAP_FRAME_Xmm5]
211 endif
212
213 /* Restore rbp */
214 mov rbp, [rbp + KTRAP_FRAME_Rbp]
215
216 /* Adjust stack pointer */
217 add rsp, KTRAP_FRAME_Rip
218
219 if (Flags AND TF_SEND_EOI)
220 /* Write 0 to the local APIC EOI register */
221 mov dword ptr [APIC_EOI], 0
222 endif
223
224 /* Return from the trap */
225 iretq
226 ENDM
227
228
229 MACRO(TRAP_ENTRY, Trap, Flags)
230 EXTERN Trap&Handler :PROC
231 PUBLIC &Trap
232 FUNC &Trap
233 /* Common code to create the trap frame */
234 EnterTrap Flags
235
236 /* Call the C handler */
237 mov rcx, rbp
238 call Trap&Handler
239
240 /* Leave */
241 ExitTrap Flags
242 ENDFUNC
243 ENDM
244