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