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