xref: /reactos/sdk/include/asm/trapamd64.inc (revision 98e8827a)
1
2APIC_EOI = HEX(0FFFFFFFFFFFE00B0)
3
4TF_VOLATILES            = HEX(01)
5TF_NONVOLATILES         = HEX(02)
6TF_XMM                  = HEX(04)
7TF_SEGMENTS             = HEX(08)
8TF_DEBUG                = HEX(10)
9TF_IRQL                 = HEX(20)
10TF_SAVE_ALL             = (TF_VOLATILES OR TF_NONVOLATILES OR TF_XMM OR TF_SEGMENTS)
11TF_HAS_ERROR_CODE       = HEX(40)
12TF_SEND_EOI             = HEX(80)
13//TF_SYSTEMSERVICE        = (TRAPFLAG_VOLATILES or TRAPFLAG_DEBUG)
14TF_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 */
31MACRO(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 MCXSR */
101    stmxcsr [rbp + KTRAP_FRAME_MxCsr]
102
103#if DBG
104    mov ecx, MSR_GS_BASE
105    rdmsr
106    mov [rbp + KTRAP_FRAME_GsBase], eax
107    mov [rbp + KTRAP_FRAME_GsBase + 4], edx
108#endif
109
110    /* Save previous mode and check if it was user mode */
111    mov ax, [rbp + KTRAP_FRAME_SegCs]
112    and al, 1
113    mov [rbp + KTRAP_FRAME_PreviousMode], al
114    jz kernel_mode_entry
115
116    /* Set sane segments */
117    mov ax, (KGDT64_R3_DATA or RPL_MASK)
118    mov ds, ax
119    mov es, ax
120    swapgs
121
122    /* Load kernel MXCSR */
123    ldmxcsr gs:[PcMxCsr]
124
125#if DBG
126    /* Check IRQL */
127    mov rax, cr8
128    test rax, rax
129    jz kernel_mode_entry
130    int HEX(2c)
131#endif
132
133kernel_mode_entry:
134
135//    if (Flags AND TF_IRQL)
136        /* Save previous irql */
137        mov rax, cr8
138        mov [rbp + KTRAP_FRAME_PreviousIrql], al
139//    endif
140
141    if (Flags AND TF_DEBUG)
142        /* Save debug registers */
143        mov rax, dr0
144        mov [rbp + KTRAP_FRAME_Dr0], rax
145        mov rax, dr1
146        mov [rbp + KTRAP_FRAME_Dr1], rax
147        mov rax, dr2
148        mov [rbp + KTRAP_FRAME_Dr2], rax
149        mov rax, dr3
150        mov [rbp + KTRAP_FRAME_Dr3], rax
151        mov rax, dr6
152        mov [rbp + KTRAP_FRAME_Dr6], rax
153        mov rax, dr7
154        mov [rbp + KTRAP_FRAME_Dr7], rax
155    endif
156
157    /* Make sure the direction flag is cleared */
158    cld
159ENDM
160
161/*
162 *  ExitTrap - Restore registers and free stack space
163 */
164MACRO(ExitTrap, Flags)
165    LOCAL kernel_mode_return
166    LOCAL IntsEnabled
167    LOCAL NoUserApc
168    LOCAL IrqlPassive
169
170#if DBG
171        /* Check previous irql */
172        mov rax, cr8
173        cmp [rbp + KTRAP_FRAME_PreviousIrql], al
174#ifdef _USE_ML
175        je .irql_ok
176#else
177        je 1f
178#endif
179        int 3
180#ifdef _USE_ML
181    .irql_ok:
182#else
183    1:
184#endif
185#endif
186
187    if (Flags AND TF_SEGMENTS)
188        /* Restore segment selectors */
189        mov ds, [rbp + KTRAP_FRAME_SegDs]
190        mov es, [rbp + KTRAP_FRAME_SegEs]
191        mov fs, [rbp + KTRAP_FRAME_SegFs]
192    endif
193
194    if (Flags AND TF_IRQL)
195        /* Restore previous irql */
196        movzx rax, byte ptr [rbp + KTRAP_FRAME_PreviousIrql]
197        mov cr8, rax
198    endif
199
200    /* Check if we came from user mode */
201    test byte ptr [rbp + KTRAP_FRAME_SegCs], 1
202    jz kernel_mode_return
203
204    if (Flags AND TF_CHECKUSERAPC)
205        /* Load current thread into r10 */
206        mov r10, gs:[PcCurrentThread]
207        cmp byte ptr [r10 + KTHREAD_UserApcPending], 0
208        je NoUserApc
209        call KiInitiateUserApc
210    NoUserApc:
211    endif
212
213#if DBG
214    /*Make sure interrupts are enabled */
215    test dword ptr [rbp + KTRAP_FRAME_EFlags], HEX(200)
216    jnz IntsEnabled
217    int HEX(2c)
218IntsEnabled:
219
220    /* Make sure we are at passive level */
221    mov rax, cr8
222    test rax, rax
223    jz IrqlPassive
224    int HEX(2C)
225
226IrqlPassive:
227#endif
228
229    cli
230
231    /* Swap gs to user mode */
232    swapgs
233
234kernel_mode_return:
235
236    if (Flags AND TF_NONVOLATILES)
237        /* Restore non-volatile registers */
238        mov rbx, [rbp + KTRAP_FRAME_Rbx]
239        mov rdi, [rbp + KTRAP_FRAME_Rdi]
240        mov rsi, [rbp + KTRAP_FRAME_Rsi]
241    endif
242
243    if (Flags AND TF_VOLATILES)
244        /* Restore volatile registers */
245        mov rax, [rbp + KTRAP_FRAME_Rax]
246        mov rcx, [rbp + KTRAP_FRAME_Rcx]
247        mov rdx, [rbp + KTRAP_FRAME_Rdx]
248        mov r8, [rbp + KTRAP_FRAME_R8]
249        mov r9, [rbp + KTRAP_FRAME_R9]
250        mov r10, [rbp + KTRAP_FRAME_R10]
251        mov r11, [rbp + KTRAP_FRAME_R11]
252    endif
253
254    if (Flags AND TF_XMM)
255        /* Restore xmm registers */
256        movdqa xmm0, [rbp + KTRAP_FRAME_Xmm0]
257        movdqa xmm1, [rbp + KTRAP_FRAME_Xmm1]
258        movdqa xmm2, [rbp + KTRAP_FRAME_Xmm2]
259        movdqa xmm3, [rbp + KTRAP_FRAME_Xmm3]
260        movdqa xmm4, [rbp + KTRAP_FRAME_Xmm4]
261        movdqa xmm5, [rbp + KTRAP_FRAME_Xmm5]
262    endif
263
264    /* Restore MCXSR */
265    ldmxcsr [rbp + KTRAP_FRAME_MxCsr]
266
267    /* Restore rbp */
268    mov rbp, [rbp + KTRAP_FRAME_Rbp]
269
270    /* Adjust stack pointer */
271    add rsp, KTRAP_FRAME_Rip
272
273    if (Flags AND TF_SEND_EOI)
274        /* Write 0 to the local APIC EOI register */
275        mov dword ptr [APIC_EOI], 0
276    endif
277
278    /* Return from the trap */
279    iretq
280ENDM
281
282
283MACRO(TRAP_ENTRY, Trap, Flags)
284    EXTERN Trap&Handler :PROC
285    PUBLIC &Trap
286    FUNC &Trap
287        /* Common code to create the trap frame */
288        EnterTrap Flags
289
290        /* Call the C handler */
291        mov rcx, rbp
292        call Trap&Handler
293
294        /* Leave */
295        ExitTrap Flags
296    ENDFUNC
297ENDM
298
299