xref: /reactos/sdk/include/asm/trapamd64.inc (revision 50cf16b3)
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 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
112kernel_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
138ENDM
139
140/*
141 *  ExitTrap - Restore registers and free stack space
142 */
143MACRO(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
183kernel_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
226ENDM
227
228
229MACRO(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
243ENDM
244
245