xref: /reactos/sdk/include/asm/trapamd64.inc (revision 9cfd8dd9)
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    LOCAL irql_ok
170
171#if DBG
172        /* Check previous irql */
173        mov rax, cr8
174        cmp [rbp + KTRAP_FRAME_PreviousIrql], al
175        je irql_ok
176        int HEX(2c)
177    irql_ok:
178#endif
179
180    if (Flags AND TF_SEGMENTS)
181        /* Restore segment selectors */
182        mov ds, [rbp + KTRAP_FRAME_SegDs]
183        mov es, [rbp + KTRAP_FRAME_SegEs]
184        mov fs, [rbp + KTRAP_FRAME_SegFs]
185    endif
186
187    if (Flags AND TF_IRQL)
188        /* Restore previous irql */
189        movzx rax, byte ptr [rbp + KTRAP_FRAME_PreviousIrql]
190        mov cr8, rax
191    endif
192
193    /* Check if we came from user mode */
194    test byte ptr [rbp + KTRAP_FRAME_SegCs], 1
195    jz kernel_mode_return
196
197    if (Flags AND TF_CHECKUSERAPC)
198        /* Load current thread into r10 */
199        mov r10, gs:[PcCurrentThread]
200        cmp byte ptr [r10 + KTHREAD_UserApcPending], 0
201        je NoUserApc
202        call KiInitiateUserApc
203    NoUserApc:
204    endif
205
206#if DBG
207    /*Make sure interrupts are enabled */
208    test dword ptr [rbp + KTRAP_FRAME_EFlags], HEX(200)
209    jnz IntsEnabled
210    int HEX(2c)
211IntsEnabled:
212
213    /* Make sure we are at passive level */
214    mov rax, cr8
215    test rax, rax
216    jz IrqlPassive
217    int HEX(2C)
218
219IrqlPassive:
220#endif
221
222    cli
223
224    /* Swap gs to user mode */
225    swapgs
226
227kernel_mode_return:
228
229    if (Flags AND TF_NONVOLATILES)
230        /* Restore non-volatile registers */
231        mov rbx, [rbp + KTRAP_FRAME_Rbx]
232        mov rdi, [rbp + KTRAP_FRAME_Rdi]
233        mov rsi, [rbp + KTRAP_FRAME_Rsi]
234    endif
235
236    if (Flags AND TF_VOLATILES)
237        /* Restore volatile registers */
238        mov rax, [rbp + KTRAP_FRAME_Rax]
239        mov rcx, [rbp + KTRAP_FRAME_Rcx]
240        mov rdx, [rbp + KTRAP_FRAME_Rdx]
241        mov r8, [rbp + KTRAP_FRAME_R8]
242        mov r9, [rbp + KTRAP_FRAME_R9]
243        mov r10, [rbp + KTRAP_FRAME_R10]
244        mov r11, [rbp + KTRAP_FRAME_R11]
245    endif
246
247    if (Flags AND TF_XMM)
248        /* Restore xmm registers */
249        movdqa xmm0, [rbp + KTRAP_FRAME_Xmm0]
250        movdqa xmm1, [rbp + KTRAP_FRAME_Xmm1]
251        movdqa xmm2, [rbp + KTRAP_FRAME_Xmm2]
252        movdqa xmm3, [rbp + KTRAP_FRAME_Xmm3]
253        movdqa xmm4, [rbp + KTRAP_FRAME_Xmm4]
254        movdqa xmm5, [rbp + KTRAP_FRAME_Xmm5]
255    endif
256
257    /* Restore MCXSR */
258    ldmxcsr [rbp + KTRAP_FRAME_MxCsr]
259
260    /* Restore rbp */
261    mov rbp, [rbp + KTRAP_FRAME_Rbp]
262
263    /* Adjust stack pointer */
264    add rsp, KTRAP_FRAME_Rip
265
266    if (Flags AND TF_SEND_EOI)
267        /* Write 0 to the local APIC EOI register */
268        mov dword ptr [APIC_EOI], 0
269    endif
270
271    /* Return from the trap */
272    iretq
273ENDM
274
275
276MACRO(TRAP_ENTRY, Trap, Flags)
277    EXTERN Trap&Handler :PROC
278    PUBLIC &Trap
279    FUNC &Trap
280        /* Common code to create the trap frame */
281        EnterTrap Flags
282
283        /* Call the C handler */
284        mov rcx, rbp
285        call Trap&Handler
286
287        /* Leave */
288        ExitTrap Flags
289    ENDFUNC
290ENDM
291
292