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