Changeset 89c57b6 in mainline for kernel/arch/amd64/src/asm.S
- Timestamp:
- 2011-04-13T14:45:41Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 88634420
- Parents:
- cefb126 (diff), 17279ead (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/arch/amd64/src/asm.S
rcefb126 r89c57b6 27 27 */ 28 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 49 29 #include <arch/pm.h> 50 30 #include <arch/mm/page.h> … … 57 37 .global read_efer_flag 58 38 .global set_efer_flag 59 .global memsetb60 .global memsetw61 .global memcpy62 39 .global memcpy_from_uspace 63 40 .global memcpy_to_uspace … … 66 43 .global early_putchar 67 44 68 /* Wrapper for generic memsetb */69 memsetb:70 jmp _memsetb71 72 /* Wrapper for generic memsetw */73 memsetw:74 jmp _memsetw75 76 45 #define MEMCPY_DST %rdi 77 46 #define MEMCPY_SRC %rsi … … 94 63 * 95 64 */ 96 memcpy:97 65 memcpy_from_uspace: 98 66 memcpy_to_uspace: … … 115 83 memcpy_from_uspace_failover_address: 116 84 memcpy_to_uspace_failover_address: 117 xor q %rax, %rax /* return 0, failure */85 xorl %eax, %eax /* return 0, failure */ 118 86 ret 119 87 … … 163 131 164 132 set_efer_flag: 165 mov q $0xc0000080, %rcx133 movl $0xc0000080, %ecx 166 134 rdmsr 167 135 btsl %edi, %eax … … 170 138 171 139 read_efer_flag: 172 mov q $0xc0000080, %rcx140 movl $0xc0000080, %ecx 173 141 rdmsr 174 142 ret 175 143 176 /** Push all volatile general purpose registers on stack 177 * 144 #define ISTATE_OFFSET_RAX 0 145 #define ISTATE_OFFSET_RBX 8 146 #define ISTATE_OFFSET_RCX 16 147 #define ISTATE_OFFSET_RDX 24 148 #define ISTATE_OFFSET_RSI 32 149 #define ISTATE_OFFSET_RDI 40 150 #define ISTATE_OFFSET_RBP 48 151 #define ISTATE_OFFSET_R8 56 152 #define ISTATE_OFFSET_R9 64 153 #define ISTATE_OFFSET_R10 72 154 #define ISTATE_OFFSET_R11 80 155 #define ISTATE_OFFSET_R12 88 156 #define ISTATE_OFFSET_R13 96 157 #define ISTATE_OFFSET_R14 104 158 #define ISTATE_OFFSET_R15 112 159 #define ISTATE_OFFSET_ALIGNMENT 120 160 #define ISTATE_OFFSET_RBP_FRAME 128 161 #define ISTATE_OFFSET_RIP_FRAME 136 162 #define ISTATE_OFFSET_ERROR_WORD 144 163 #define ISTATE_OFFSET_RIP 152 164 #define ISTATE_OFFSET_CS 160 165 #define ISTATE_OFFSET_RFLAGS 168 166 #define ISTATE_OFFSET_RSP 176 167 #define ISTATE_OFFSET_SS 184 168 169 /* 170 * Size of the istate structure without the hardware-saved part and without the 171 * error word. 178 172 */ 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(). 173 #define ISTATE_SOFT_SIZE 144 174 175 /** 176 * Mask for interrupts 0 - 31 (bits 0 - 31) where 0 means that int 177 * has no error word and 1 means interrupt with error word 213 178 * 214 179 */ 215 .macro handler i n 216 180 #define ERROR_WORD_INTERRUPT_LIST 0x00027D00 181 182 .macro handler i 183 .global int_\i 184 int_\i: 185 217 186 /* 218 187 * 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. 188 * code. 224 189 */ 225 190 … … 229 194 * Version with error word. 230 195 */ 231 subq $I REGISTER_SPACE, %rsp196 subq $ISTATE_SOFT_SIZE, %rsp 232 197 .else 233 198 /* 234 * Version without error word ,199 * Version without error word. 235 200 */ 236 subq $(I REGISTER_SPACE + 8), %rsp201 subq $(ISTATE_SOFT_SIZE + 8), %rsp 237 202 .endif 238 203 .else 239 204 /* 240 * Version without error word ,205 * Version without error word. 241 206 */ 242 subq $(I REGISTER_SPACE + 8), %rsp207 subq $(ISTATE_SOFT_SIZE + 8), %rsp 243 208 .endif 244 209 245 save_all_gpr 210 /* 211 * Save the general purpose registers. 212 */ 213 movq %rax, ISTATE_OFFSET_RAX(%rsp) 214 movq %rbx, ISTATE_OFFSET_RBX(%rsp) 215 movq %rcx, ISTATE_OFFSET_RCX(%rsp) 216 movq %rdx, ISTATE_OFFSET_RDX(%rsp) 217 movq %rsi, ISTATE_OFFSET_RSI(%rsp) 218 movq %rdi, ISTATE_OFFSET_RDI(%rsp) 219 movq %rbp, ISTATE_OFFSET_RBP(%rsp) 220 movq %r8, ISTATE_OFFSET_R8(%rsp) 221 movq %r9, ISTATE_OFFSET_R9(%rsp) 222 movq %r10, ISTATE_OFFSET_R10(%rsp) 223 movq %r11, ISTATE_OFFSET_R11(%rsp) 224 movq %r12, ISTATE_OFFSET_R12(%rsp) 225 movq %r13, ISTATE_OFFSET_R13(%rsp) 226 movq %r14, ISTATE_OFFSET_R14(%rsp) 227 movq %r15, ISTATE_OFFSET_R15(%rsp) 228 229 /* 230 * Imitate a regular stack frame linkage. 231 * Stop stack traces here if we came from userspace. 232 */ 233 xorl %edx, %edx 234 cmpq $(GDT_SELECTOR(KTEXT_DES)), ISTATE_OFFSET_CS(%rsp) 235 cmovnzq %rdx, %rbp 236 237 movq %rbp, ISTATE_OFFSET_RBP_FRAME(%rsp) 238 movq ISTATE_OFFSET_RIP(%rsp), %rax 239 movq %rax, ISTATE_OFFSET_RIP_FRAME(%rsp) 240 leaq ISTATE_OFFSET_RBP_FRAME(%rsp), %rbp 241 242 movq $(\i), %rdi /* pass intnum in the first argument */ 243 movq %rsp, %rsi /* pass istate address in the second argument */ 244 246 245 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 246 259 247 /* Call exc_dispatch(i, istate) */ 260 248 call exc_dispatch 261 262 restore_all_gpr 249 250 /* 251 * Restore all scratch registers and the preserved registers we have 252 * clobbered in this handler (i.e. RBP). 253 */ 254 movq ISTATE_OFFSET_RAX(%rsp), %rax 255 movq ISTATE_OFFSET_RCX(%rsp), %rcx 256 movq ISTATE_OFFSET_RDX(%rsp), %rdx 257 movq ISTATE_OFFSET_RSI(%rsp), %rsi 258 movq ISTATE_OFFSET_RDI(%rsp), %rdi 259 movq ISTATE_OFFSET_RBP(%rsp), %rbp 260 movq ISTATE_OFFSET_R8(%rsp), %r8 261 movq ISTATE_OFFSET_R9(%rsp), %r9 262 movq ISTATE_OFFSET_R10(%rsp), %r10 263 movq ISTATE_OFFSET_R11(%rsp), %r11 263 264 264 265 /* $8 = Skip error word */ 265 addq $(I REGISTER_SPACE + 8), %rsp266 addq $(ISTATE_SOFT_SIZE + 8), %rsp 266 267 iretq 267 268 .align INTERRUPT_ALIGN269 .if (\n - \i) - 1270 handler "(\i + 1)", \n271 .endif272 268 .endm 273 269 274 .align INTERRUPT_ALIGN 270 #define LIST_0_63 \ 271 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,\ 272 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,\ 273 53,54,55,56,57,58,59,60,61,62,63 274 275 275 interrupt_handlers: 276 h_start: 277 handler 0 IDT_ITEMS278 h_end: 276 .irp cnt, LIST_0_63 277 handler \cnt 278 .endr 279 279 280 280 /** Low-level syscall handler … … 309 309 movq %gs:8, %rsp /* set this thread's kernel RSP */ 310 310 311 /* Switch back to remain consistent */ 311 /* 312 * Note that the space needed for the imitated istate structure has been 313 * preallocated for us in thread_create_arch() and set in 314 * before_thread_runs_arch(). 315 */ 316 317 /* 318 * Save the general purpose registers and push the 7th argument (syscall 319 * number) onto the stack. Note that the istate structure has a layout 320 * which supports this. 321 */ 322 movq %rax, ISTATE_OFFSET_RAX(%rsp) /* 7th argument, passed on stack */ 323 movq %rbx, ISTATE_OFFSET_RBX(%rsp) /* observability */ 324 movq %rcx, ISTATE_OFFSET_RCX(%rsp) /* userspace RIP */ 325 movq %rdx, ISTATE_OFFSET_RDX(%rsp) /* 3rd argument, observability */ 326 movq %rsi, ISTATE_OFFSET_RSI(%rsp) /* 2nd argument, observability */ 327 movq %rdi, ISTATE_OFFSET_RDI(%rsp) /* 1st argument, observability */ 328 movq %rbp, ISTATE_OFFSET_RBP(%rsp) /* need to preserve userspace RBP */ 329 movq %r8, ISTATE_OFFSET_R8(%rsp) /* 5th argument, observability */ 330 movq %r9, ISTATE_OFFSET_R9(%rsp) /* 6th argument, observability */ 331 movq %r10, ISTATE_OFFSET_R10(%rsp) /* 4th argument, observability */ 332 movq %r11, ISTATE_OFFSET_R11(%rsp) /* low 32 bits userspace RFLAGS */ 333 movq %r12, ISTATE_OFFSET_R12(%rsp) /* observability */ 334 movq %r13, ISTATE_OFFSET_R13(%rsp) /* observability */ 335 movq %r14, ISTATE_OFFSET_R14(%rsp) /* observability */ 336 movq %r15, ISTATE_OFFSET_R15(%rsp) /* observability */ 337 338 /* 339 * Save the return address and the userspace stack on locations that 340 * would normally be taken by them. 341 */ 342 movq %gs:0, %rax 343 movq %rax, ISTATE_OFFSET_RSP(%rsp) 344 movq %rcx, ISTATE_OFFSET_RIP(%rsp) 345 346 /* 347 * Imitate a regular stack frame linkage. 348 */ 349 movq $0, ISTATE_OFFSET_RBP_FRAME(%rsp) 350 movq %rcx, ISTATE_OFFSET_RIP_FRAME(%rsp) 351 leaq ISTATE_OFFSET_RBP_FRAME(%rsp), %rbp 352 353 /* Switch back to normal %gs */ 312 354 swapgs 313 355 sti 314 356 315 pushq %rcx316 pushq %r11317 pushq %rbp318 319 xorq %rbp, %rbp /* stop the stack traces here */320 321 357 /* Copy the 4th argument where it is expected */ 322 358 movq %r10, %rcx 323 pushq %rax 324 359 360 /* 361 * Call syscall_handler() with the 7th argument passed on stack. 362 */ 325 363 call syscall_handler 326 364 327 addq $8, %rsp328 329 popq %rbp330 popq %r11331 popq %rcx332 333 365 cli 334 swapgs 335 336 /* Restore the user RSP */ 337 movq %gs:0, %rsp 338 swapgs 339 366 367 /* 368 * Restore registers needed for return via the SYSRET instruction and 369 * the clobbered preserved registers (i.e. RBP). 370 */ 371 movq ISTATE_OFFSET_RBP(%rsp), %rbp 372 movq ISTATE_OFFSET_RCX(%rsp), %rcx 373 movq ISTATE_OFFSET_R11(%rsp), %r11 374 movq ISTATE_OFFSET_RSP(%rsp), %rsp 375 376 /* 377 * Clear the rest of the scratch registers to prevent information leak. 378 * The 32-bit XOR on the low GPRs actually clears the entire 64-bit 379 * register and the instruction is shorter. 380 */ 381 xorl %edx, %edx 382 xorl %esi, %esi 383 xorl %edi, %edi 384 xorq %r8, %r8 385 xorq %r9, %r9 386 xorq %r10, %r10 387 340 388 sysretq 341 389 … … 347 395 * Since the EGA can only display Extended ASCII (usually 348 396 * ISO Latin 1) characters, some of the Unicode characters 349 * can be displayed in a wrong way. Only the newline character350 * isinterpreted, all other characters (even unprintable) are397 * can be displayed in a wrong way. Only newline and backspace 398 * are interpreted, all other characters (even unprintable) are 351 399 * printed verbatim. 352 400 * … … 365 413 movq %rdi, %rsi 366 414 movq $(PA2KA(0xb8000)), %rdi /* base of EGA text mode memory */ 367 xor q %rax, %rax415 xorl %eax, %eax 368 416 369 417 /* Read bits 8 - 15 of the cursor address */ … … 399 447 400 448 cmp $0x0a, %al 401 jne early_putchar_ print449 jne early_putchar_backspace 402 450 403 451 /* Interpret newline */ … … 413 461 subw %dx, %bx 414 462 415 jmp early_putchar_newline 463 jmp early_putchar_skip 464 465 early_putchar_backspace: 466 467 cmp $0x08, %al 468 jne early_putchar_print 469 470 /* Interpret backspace */ 471 472 cmp $0x0000, %bx 473 je early_putchar_skip 474 475 dec %bx 476 jmp early_putchar_skip 416 477 417 478 early_putchar_print: … … 423 484 inc %bx 424 485 425 early_putchar_ newline:486 early_putchar_skip: 426 487 427 488 /* Sanity check for the cursor on the last line */ … … 432 493 movq $(PA2KA(0xb80a0)), %rsi 433 494 movq $(PA2KA(0xb8000)), %rdi 434 mov q $1920, %rcx435 rep movs w495 movl $480, %ecx 496 rep movsq 436 497 437 498 /* Clear the 24th row */ 438 xor q %rax, %rax439 mov q $80, %rcx440 rep stos w499 xorl %eax, %eax 500 movl $20, %ecx 501 rep stosq 441 502 442 503 /* Go to row 24 */ … … 471 532 ret 472 533 473 .data474 .global interrupt_handler_size475 476 interrupt_handler_size: .quad (h_end - h_start) / IDT_ITEMS
Note:
See TracChangeset
for help on using the changeset viewer.