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