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