Changes in kernel/arch/amd64/src/asm.S [22c3444:f77e591d] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/arch/amd64/src/asm.S
r22c3444 rf77e591d 26 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 27 */ 28 29 #define IREGISTER_SPACE 8030 31 #define IOFFSET_RAX 0x0032 #define IOFFSET_RCX 0x0833 #define IOFFSET_RDX 0x1034 #define IOFFSET_RSI 0x1835 #define IOFFSET_RDI 0x2036 #define IOFFSET_R8 0x2837 #define IOFFSET_R9 0x3038 #define IOFFSET_R10 0x3839 #define IOFFSET_R11 0x4040 #define IOFFSET_RBP 0x4841 42 /**43 * Mask for interrupts 0 - 31 (bits 0 - 31) where 0 means that int44 * has no error word and 1 means interrupt with error word45 *46 */47 #define ERROR_WORD_INTERRUPT_LIST 0x00027D0048 28 49 29 #include <arch/pm.h> … … 174 154 ret 175 155 176 /** Push all volatile general purpose registers on stack 177 * 156 #define ISTATE_OFFSET_RAX 0 157 #define ISTATE_OFFSET_RBX 8 158 #define ISTATE_OFFSET_RCX 16 159 #define ISTATE_OFFSET_RDX 24 160 #define ISTATE_OFFSET_RSI 32 161 #define ISTATE_OFFSET_RDI 40 162 #define ISTATE_OFFSET_RBP 48 163 #define ISTATE_OFFSET_R8 56 164 #define ISTATE_OFFSET_R9 64 165 #define ISTATE_OFFSET_R10 72 166 #define ISTATE_OFFSET_R11 80 167 #define ISTATE_OFFSET_R12 88 168 #define ISTATE_OFFSET_R13 96 169 #define ISTATE_OFFSET_R14 104 170 #define ISTATE_OFFSET_R15 112 171 #define ISTATE_OFFSET_ALIGNMENT 120 172 #define ISTATE_OFFSET_RBP_FRAME 128 173 #define ISTATE_OFFSET_RIP_FRAME 136 174 #define ISTATE_OFFSET_ERROR_WORD 144 175 #define ISTATE_OFFSET_RIP 152 176 #define ISTATE_OFFSET_CS 160 177 #define ISTATE_OFFSET_RFLAGS 168 178 #define ISTATE_OFFSET_RSP 176 179 #define ISTATE_OFFSET_SS 184 180 181 /* 182 * Size of the istate structure without the hardware-saved part and without the 183 * error word. 178 184 */ 179 .macro save_all_gpr 180 movq %rax, IOFFSET_RAX(%rsp) 181 movq %rcx, IOFFSET_RCX(%rsp) 182 movq %rdx, IOFFSET_RDX(%rsp) 183 movq %rsi, IOFFSET_RSI(%rsp) 184 movq %rdi, IOFFSET_RDI(%rsp) 185 movq %r8, IOFFSET_R8(%rsp) 186 movq %r9, IOFFSET_R9(%rsp) 187 movq %r10, IOFFSET_R10(%rsp) 188 movq %r11, IOFFSET_R11(%rsp) 189 movq %rbp, IOFFSET_RBP(%rsp) 190 .endm 191 192 .macro restore_all_gpr 193 movq IOFFSET_RAX(%rsp), %rax 194 movq IOFFSET_RCX(%rsp), %rcx 195 movq IOFFSET_RDX(%rsp), %rdx 196 movq IOFFSET_RSI(%rsp), %rsi 197 movq IOFFSET_RDI(%rsp), %rdi 198 movq IOFFSET_R8(%rsp), %r8 199 movq IOFFSET_R9(%rsp), %r9 200 movq IOFFSET_R10(%rsp), %r10 201 movq IOFFSET_R11(%rsp), %r11 202 movq IOFFSET_RBP(%rsp), %rbp 203 .endm 204 205 #define INTERRUPT_ALIGN 128 206 207 /** Declare interrupt handlers 208 * 209 * Declare interrupt handlers for n interrupt 210 * vectors starting at vector i. 211 * 212 * The handlers call exc_dispatch(). 185 #define ISTATE_SOFT_SIZE 144 186 187 /** 188 * Mask for interrupts 0 - 31 (bits 0 - 31) where 0 means that int 189 * has no error word and 1 means interrupt with error word 213 190 * 214 191 */ 215 .macro handler i n 216 192 #define ERROR_WORD_INTERRUPT_LIST 0x00027D00 193 194 .macro handler i 195 .global int_\i 196 int_\i: 197 217 198 /* 218 199 * Choose between version with error code and version without error 219 * code. Both versions have to be of the same size. amd64 assembly is, 220 * however, a little bit tricky. For instance, subq $0x80, %rsp and 221 * subq $0x78, %rsp can result in two instructions with different 222 * op-code lengths. 223 * Therefore we align the interrupt handlers. 200 * code. 224 201 */ 225 202 … … 229 206 * Version with error word. 230 207 */ 231 subq $I REGISTER_SPACE, %rsp208 subq $ISTATE_SOFT_SIZE, %rsp 232 209 .else 233 210 /* 234 * Version without error word ,211 * Version without error word. 235 212 */ 236 subq $(I REGISTER_SPACE + 8), %rsp213 subq $(ISTATE_SOFT_SIZE + 8), %rsp 237 214 .endif 238 215 .else 239 216 /* 240 * Version without error word ,217 * Version without error word. 241 218 */ 242 subq $(I REGISTER_SPACE + 8), %rsp219 subq $(ISTATE_SOFT_SIZE + 8), %rsp 243 220 .endif 244 221 245 save_all_gpr 222 /* 223 * Save the general purpose registers. 224 */ 225 movq %rax, ISTATE_OFFSET_RAX(%rsp) 226 movq %rbx, ISTATE_OFFSET_RBX(%rsp) 227 movq %rcx, ISTATE_OFFSET_RCX(%rsp) 228 movq %rdx, ISTATE_OFFSET_RDX(%rsp) 229 movq %rsi, ISTATE_OFFSET_RSI(%rsp) 230 movq %rdi, ISTATE_OFFSET_RDI(%rsp) 231 movq %rbp, ISTATE_OFFSET_RBP(%rsp) 232 movq %r8, ISTATE_OFFSET_R8(%rsp) 233 movq %r9, ISTATE_OFFSET_R9(%rsp) 234 movq %r10, ISTATE_OFFSET_R10(%rsp) 235 movq %r11, ISTATE_OFFSET_R11(%rsp) 236 movq %r12, ISTATE_OFFSET_R12(%rsp) 237 movq %r13, ISTATE_OFFSET_R13(%rsp) 238 movq %r14, ISTATE_OFFSET_R14(%rsp) 239 movq %r15, ISTATE_OFFSET_R15(%rsp) 240 241 /* 242 * Imitate a regular stack frame linkage. 243 * Stop stack traces here if we came from userspace. 244 */ 245 xorq %rdx, %rdx 246 cmpq $(gdtselector(KTEXT_DES)), ISTATE_OFFSET_CS(%rsp) 247 cmovnzq %rdx, %rbp 248 249 movq %rbp, ISTATE_OFFSET_RBP_FRAME(%rsp) 250 movq ISTATE_OFFSET_RIP(%rsp), %rax 251 movq %rax, ISTATE_OFFSET_RIP_FRAME(%rsp) 252 leaq ISTATE_OFFSET_RBP_FRAME(%rsp), %rbp 253 254 movq $(\i), %rdi /* pass intnum in the first argument */ 255 movq %rsp, %rsi /* pass istate address in the second argument */ 256 246 257 cld 247 248 /* 249 * Stop stack traces here if we came from userspace. 250 */ 251 movq %cs, %rax 252 xorq %rdx, %rdx 253 cmpq %rax, IREGISTER_SPACE+16(%rsp) 254 cmovneq %rdx, %rbp 255 256 movq $(\i), %rdi /* %rdi - first argument */ 257 movq %rsp, %rsi /* %rsi - pointer to istate */ 258 258 259 259 /* Call exc_dispatch(i, istate) */ 260 260 call exc_dispatch 261 262 restore_all_gpr 261 262 /* 263 * Restore all scratch registers and the preserved registers we have 264 * clobbered in this handler (i.e. RBP). 265 */ 266 movq ISTATE_OFFSET_RAX(%rsp), %rax 267 movq ISTATE_OFFSET_RCX(%rsp), %rcx 268 movq ISTATE_OFFSET_RDX(%rsp), %rdx 269 movq ISTATE_OFFSET_RSI(%rsp), %rsi 270 movq ISTATE_OFFSET_RDI(%rsp), %rdi 271 movq ISTATE_OFFSET_RBP(%rsp), %rbp 272 movq ISTATE_OFFSET_R8(%rsp), %r8 273 movq ISTATE_OFFSET_R9(%rsp), %r9 274 movq ISTATE_OFFSET_R10(%rsp), %r10 275 movq ISTATE_OFFSET_R11(%rsp), %r11 263 276 264 277 /* $8 = Skip error word */ 265 addq $(I REGISTER_SPACE + 8), %rsp278 addq $(ISTATE_SOFT_SIZE + 8), %rsp 266 279 iretq 267 268 .align INTERRUPT_ALIGN269 .if (\n - \i) - 1270 handler "(\i + 1)", \n271 .endif272 280 .endm 273 281 274 .align INTERRUPT_ALIGN 282 #define LIST_0_63 \ 283 0, 1, 2, 3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,\ 284 28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,\ 285 53,54,55,56,57,58,59,60,61,62,63 286 275 287 interrupt_handlers: 276 h_start: 277 handler 0 IDT_ITEMS278 h_end: 288 .irp cnt, LIST_0_63 289 handler \cnt 290 .endr 279 291 280 292 /** Low-level syscall handler … … 309 321 movq %gs:8, %rsp /* set this thread's kernel RSP */ 310 322 311 /* Switch back to remain consistent */ 323 /* 324 * Note that the space needed for the imitated istate structure has been 325 * preallocated for us in thread_create_arch() and set in 326 * before_thread_runs_arch(). 327 */ 328 329 /* 330 * Save the general purpose registers and push the 7th argument (syscall 331 * number) onto the stack. Note that the istate structure has a layout 332 * which supports this. 333 */ 334 movq %rax, ISTATE_OFFSET_RAX(%rsp) /* 7th argument, passed on stack */ 335 movq %rbx, ISTATE_OFFSET_RBX(%rsp) /* observability */ 336 movq %rcx, ISTATE_OFFSET_RCX(%rsp) /* userspace RIP */ 337 movq %rdx, ISTATE_OFFSET_RDX(%rsp) /* 3rd argument, observability */ 338 movq %rsi, ISTATE_OFFSET_RSI(%rsp) /* 2nd argument, observability */ 339 movq %rdi, ISTATE_OFFSET_RDI(%rsp) /* 1st argument, observability */ 340 movq %rbp, ISTATE_OFFSET_RBP(%rsp) /* need to preserve userspace RBP */ 341 movq %r8, ISTATE_OFFSET_R8(%rsp) /* 5th argument, observability */ 342 movq %r9, ISTATE_OFFSET_R9(%rsp) /* 6th argument, observability */ 343 movq %r10, ISTATE_OFFSET_R10(%rsp) /* 4th argument, observability */ 344 movq %r11, ISTATE_OFFSET_R11(%rsp) /* low 32 bits userspace RFLAGS */ 345 movq %r12, ISTATE_OFFSET_R12(%rsp) /* observability */ 346 movq %r13, ISTATE_OFFSET_R13(%rsp) /* observability */ 347 movq %r14, ISTATE_OFFSET_R14(%rsp) /* observability */ 348 movq %r15, ISTATE_OFFSET_R15(%rsp) /* observability */ 349 350 /* 351 * Save the return address and the userspace stack on locations that 352 * would normally be taken by them. 353 */ 354 movq %gs:0, %rax 355 movq %rax, ISTATE_OFFSET_RSP(%rsp) 356 movq %rcx, ISTATE_OFFSET_RIP(%rsp) 357 358 /* 359 * Imitate a regular stack frame linkage. 360 */ 361 movq $0, ISTATE_OFFSET_RBP_FRAME(%rsp) 362 movq %rcx, ISTATE_OFFSET_RIP_FRAME(%rsp) 363 leaq ISTATE_OFFSET_RBP_FRAME(%rsp), %rbp 364 365 /* Switch back to normal %gs */ 312 366 swapgs 313 367 sti 314 368 315 pushq %rcx316 pushq %r11317 pushq %rbp318 319 xorq %rbp, %rbp /* stop the stack traces here */320 321 369 /* Copy the 4th argument where it is expected */ 322 370 movq %r10, %rcx 323 pushq %rax 324 371 372 /* 373 * Call syscall_handler() with the 7th argument passed on stack. 374 */ 325 375 call syscall_handler 326 376 327 addq $8, %rsp328 329 popq %rbp330 popq %r11331 popq %rcx332 333 377 cli 334 swapgs 335 336 /* Restore the user RSP */ 337 movq %gs:0, %rsp 338 swapgs 339 378 379 /* 380 * Restore registers needed for return via the SYSRET instruction and 381 * the clobbered preserved registers (i.e. RBP). 382 */ 383 movq ISTATE_OFFSET_RBP(%rsp), %rbp 384 movq ISTATE_OFFSET_RCX(%rsp), %rcx 385 movq ISTATE_OFFSET_R11(%rsp), %r11 386 movq ISTATE_OFFSET_RSP(%rsp), %rsp 387 340 388 sysretq 341 389 … … 484 532 ret 485 533 486 .data487 .global interrupt_handler_size488 489 interrupt_handler_size: .quad (h_end - h_start) / IDT_ITEMS
Note:
See TracChangeset
for help on using the changeset viewer.