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 LOCAL irql_ok 170 171#if DBG 172 /* Check previous irql */ 173 mov rax, cr8 174 cmp [rbp + KTRAP_FRAME_PreviousIrql], al 175 je irql_ok 176 int HEX(2c) 177 irql_ok: 178#endif 179 180 if (Flags AND TF_SEGMENTS) 181 /* Restore segment selectors */ 182 mov ds, [rbp + KTRAP_FRAME_SegDs] 183 mov es, [rbp + KTRAP_FRAME_SegEs] 184 mov fs, [rbp + KTRAP_FRAME_SegFs] 185 endif 186 187 if (Flags AND TF_IRQL) 188 /* Restore previous irql */ 189 movzx rax, byte ptr [rbp + KTRAP_FRAME_PreviousIrql] 190 mov cr8, rax 191 endif 192 193 /* Check if we came from user mode */ 194 test byte ptr [rbp + KTRAP_FRAME_SegCs], 1 195 jz kernel_mode_return 196 197 if (Flags AND TF_CHECKUSERAPC) 198 /* Load current thread into r10 */ 199 mov r10, gs:[PcCurrentThread] 200 cmp byte ptr [r10 + KTHREAD_UserApcPending], 0 201 je NoUserApc 202 call KiInitiateUserApc 203 NoUserApc: 204 endif 205 206#if DBG 207 /*Make sure interrupts are enabled */ 208 test dword ptr [rbp + KTRAP_FRAME_EFlags], HEX(200) 209 jnz IntsEnabled 210 int HEX(2c) 211IntsEnabled: 212 213 /* Make sure we are at passive level */ 214 mov rax, cr8 215 test rax, rax 216 jz IrqlPassive 217 int HEX(2C) 218 219IrqlPassive: 220#endif 221 222 cli 223 224 /* Swap gs to user mode */ 225 swapgs 226 227kernel_mode_return: 228 229 if (Flags AND TF_NONVOLATILES) 230 /* Restore non-volatile registers */ 231 mov rbx, [rbp + KTRAP_FRAME_Rbx] 232 mov rdi, [rbp + KTRAP_FRAME_Rdi] 233 mov rsi, [rbp + KTRAP_FRAME_Rsi] 234 endif 235 236 if (Flags AND TF_VOLATILES) 237 /* Restore volatile registers */ 238 mov rax, [rbp + KTRAP_FRAME_Rax] 239 mov rcx, [rbp + KTRAP_FRAME_Rcx] 240 mov rdx, [rbp + KTRAP_FRAME_Rdx] 241 mov r8, [rbp + KTRAP_FRAME_R8] 242 mov r9, [rbp + KTRAP_FRAME_R9] 243 mov r10, [rbp + KTRAP_FRAME_R10] 244 mov r11, [rbp + KTRAP_FRAME_R11] 245 endif 246 247 if (Flags AND TF_XMM) 248 /* Restore xmm registers */ 249 movdqa xmm0, [rbp + KTRAP_FRAME_Xmm0] 250 movdqa xmm1, [rbp + KTRAP_FRAME_Xmm1] 251 movdqa xmm2, [rbp + KTRAP_FRAME_Xmm2] 252 movdqa xmm3, [rbp + KTRAP_FRAME_Xmm3] 253 movdqa xmm4, [rbp + KTRAP_FRAME_Xmm4] 254 movdqa xmm5, [rbp + KTRAP_FRAME_Xmm5] 255 endif 256 257 /* Restore MCXSR */ 258 ldmxcsr [rbp + KTRAP_FRAME_MxCsr] 259 260 /* Restore rbp */ 261 mov rbp, [rbp + KTRAP_FRAME_Rbp] 262 263 /* Adjust stack pointer */ 264 add rsp, KTRAP_FRAME_Rip 265 266 if (Flags AND TF_SEND_EOI) 267 /* Write 0 to the local APIC EOI register */ 268 mov dword ptr [APIC_EOI], 0 269 endif 270 271 /* Return from the trap */ 272 iretq 273ENDM 274 275 276MACRO(TRAP_ENTRY, Trap, Flags) 277 EXTERN Trap&Handler :PROC 278 PUBLIC &Trap 279 FUNC &Trap 280 /* Common code to create the trap frame */ 281 EnterTrap Flags 282 283 /* Call the C handler */ 284 mov rcx, rbp 285 call Trap&Handler 286 287 /* Leave */ 288 ExitTrap Flags 289 ENDFUNC 290ENDM 291 292