1/* 2 * Copyright 2002-2016, The Haiku Team. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Copyright 2001, Travis Geiselbrecht. All rights reserved. 6 * Copyright 2002, Michael Noisternig. All rights reserved. 7 * Distributed under the terms of the NewOS License. 8 */ 9 10#include <arch/user_debugger.h> 11#include <arch/x86/arch_cpu.h> 12#include <arch/x86/arch_kernel.h> 13#include <arch/x86/descriptors.h> 14#include <asm_defs.h> 15#include <commpage_defs.h> 16#include <thread_types.h> 17 18#include "tracing_config.h" 19 20#include "asm_offsets.h" 21#include "syscall_numbers.h" 22#include "syscall_table.h" 23 24 25#define LOCK_THREAD_TIME() \ 26 lea THREAD_time_lock(%edi), %eax; \ 27 pushl %eax; \ 28 call acquire_spinlock; 29 /* leave spinlock address on stack for UNLOCK_THREAD_TIME() */ 30 31#define UNLOCK_THREAD_TIME() \ 32 /* spinlock address still on stack from */ \ 33 /* LOCK_THREAD_TIME() */ \ 34 call release_spinlock; \ 35 addl $4, %esp; 36 37#define UPDATE_THREAD_USER_TIME_COMMON() \ 38 movl %eax, %ebx; /* save for later */ \ 39 movl %edx, %ecx; \ 40 \ 41 /* thread->user_time += now - thread->last_time; */ \ 42 sub THREAD_last_time(%edi), %eax; \ 43 sbb (THREAD_last_time + 4)(%edi), %edx; \ 44 add %eax, THREAD_user_time(%edi); \ 45 adc %edx, (THREAD_user_time + 4)(%edi); \ 46 \ 47 /* thread->last_time = now; */ \ 48 movl %ebx, THREAD_last_time(%edi); \ 49 movl %ecx, (THREAD_last_time + 4)(%edi); \ 50 \ 51 /* thread->in_kernel = true; */ \ 52 movb $1, THREAD_in_kernel(%edi); 53 54#define UPDATE_THREAD_USER_TIME() \ 55 LOCK_THREAD_TIME() \ 56 call system_time; \ 57 UPDATE_THREAD_USER_TIME_COMMON() \ 58 UNLOCK_THREAD_TIME() 59 60#define UPDATE_THREAD_USER_TIME_PUSH_TIME() \ 61 call system_time; \ 62 push %edx; \ 63 push %eax; \ 64 \ 65 LOCK_THREAD_TIME() \ 66 \ 67 /* recover the system time, note that */ \ 68 /* LOCK_THREAD_TIME() leaves an address on the stack */ \ 69 movl 4(%esp), %eax; \ 70 movl 8(%esp), %edx; \ 71 \ 72 UPDATE_THREAD_USER_TIME_COMMON() \ 73 \ 74 UNLOCK_THREAD_TIME() 75 76#define UPDATE_THREAD_KERNEL_TIME() \ 77 LOCK_THREAD_TIME() \ 78 \ 79 call system_time; \ 80 \ 81 movl %eax, %ebx; /* save for later */ \ 82 movl %edx, %ecx; \ 83 \ 84 /* thread->kernel_time += now - thread->last_time; */ \ 85 sub THREAD_last_time(%edi), %eax; \ 86 sbb (THREAD_last_time + 4)(%edi), %edx; \ 87 add %eax, THREAD_kernel_time(%edi); \ 88 adc %edx, (THREAD_kernel_time + 4)(%edi); \ 89 \ 90 /* thread->last_time = now; */ \ 91 movl %ebx, THREAD_last_time(%edi); \ 92 movl %ecx, (THREAD_last_time + 4)(%edi); \ 93 \ 94 /* thread->in_kernel = false; */ \ 95 movb $0, THREAD_in_kernel(%edi); \ 96 \ 97 UNLOCK_THREAD_TIME() \ 98 99#define PUSH_IFRAME_BOTTOM(iframeType) \ 100 pusha; \ 101 push %ds; \ 102 push %es; \ 103 push %fs; \ 104 push %gs; \ 105 pushl $iframeType 106 107#define PUSH_IFRAME_BOTTOM_SYSCALL() \ 108 pushl $0; \ 109 pushl $99; \ 110 pushl %edx; \ 111 pushl %eax; \ 112 PUSH_IFRAME_BOTTOM(IFRAME_TYPE_SYSCALL) 113 114#define POP_IFRAME_AND_RETURN() \ 115 /* skip iframe type */ \ 116 lea 4(%ebp), %esp; \ 117 \ 118 pop %gs; \ 119 addl $4, %esp; /* we skip %fs, as this contains the CPU \ 120 dependent TLS segment */ \ 121 pop %es; \ 122 pop %ds; \ 123 \ 124 popa; \ 125 addl $16,%esp; /* ignore the vector, error code, and \ 126 original eax/edx values */ \ 127 iret 128 129#define STOP_USER_DEBUGGING() \ 130 testl $(THREAD_FLAGS_BREAKPOINTS_INSTALLED \ 131 | THREAD_FLAGS_SINGLE_STEP), THREAD_flags(%edi); \ 132 jz 1f; \ 133 call x86_exit_user_debug_at_kernel_entry; \ 134 1: 135 136#define COPY_SYSCALL_PARAMETERS() \ 137 /* make room for the syscall params */ \ 138 subl $80, %esp; \ 139 \ 140 /* get the address of the syscall parameters */ \ 141 movl IFRAME_user_sp(%ebp), %esi; \ 142 addl $4, %esi; \ 143 cmp $KERNEL_BASE, %esi; /* must not be a kernel address */ \ 144 jae bad_syscall_params; \ 145 \ 146 /* set the fault handler */ \ 147 movl $bad_syscall_params, THREAD_fault_handler(%edi); \ 148 \ 149 /* target address is our stack */ \ 150 movl %esp, %edi; \ 151 \ 152 /* number of syscall parameter words */ \ 153 movl SYSCALL_INFO_parameter_size(%edx), %ecx; \ 154 shrl $2, %ecx; \ 155 \ 156 /* copy */ \ 157 cld; \ 158 rep movsl; \ 159 \ 160 /* restore pointers and clear fault handler */ \ 161 movl %edx, %esi; /* syscall info pointer */ \ 162 movl %gs:0, %edi; /* thread pointer */ \ 163 movl $0, THREAD_fault_handler(%edi) 164 165#if SYSCALL_TRACING 166# define TRACE_PRE_SYSCALL() \ 167 movl %esp, %eax; /* syscall parameters */ \ 168 push %eax; \ 169 movl IFRAME_orig_eax(%ebp), %eax; /* syscall number */ \ 170 push %eax; \ 171 call trace_pre_syscall; \ 172 addl $8, %esp; 173 174# define TRACE_POST_SYSCALL() \ 175 push %edx; /* syscall return value */ \ 176 push %eax; \ 177 movl IFRAME_orig_eax(%ebp), %eax; /* syscall number */ \ 178 push %eax; \ 179 call trace_post_syscall; \ 180 addl $12, %esp 181#else 182# define TRACE_PRE_SYSCALL() 183# define TRACE_POST_SYSCALL() 184#endif 185 186 187.text 188 189#define TRAP_ERRC(name, vector) \ 190.align 8; \ 191FUNCTION(name): \ 192 pushl $vector; \ 193 pushl %edx; \ 194 pushl %eax; \ 195 jmp int_bottom; \ 196FUNCTION_END(name) 197 198#define TRAP(name, vector) \ 199.align 8; \ 200FUNCTION(name): \ 201 pushl $0; \ 202 pushl $vector; \ 203 pushl %edx; \ 204 pushl %eax; \ 205 jmp int_bottom; \ 206FUNCTION_END(name) 207 208TRAP(trap0, 0) 209TRAP(trap1, 1) 210TRAP(trap2, 2) 211TRAP(trap3, 3) 212TRAP(trap4, 4) 213TRAP(trap5, 5) 214TRAP(trap6, 6) 215TRAP(trap7, 7) 216 217.align 8; 218FUNCTION(double_fault): 219 pushl $-1; // user-ss 220 pushl $-1; // user-esp 221 pushl $-1; // flags 222 pushl $KERNEL_CODE_SELECTOR // cs 223 pushl $-1; // eip 224 pushl $0; // error-code 225 pushl $8; 226 pushl $-1; 227 pushl $-1; 228 229 PUSH_IFRAME_BOTTOM(IFRAME_TYPE_OTHER) 230 231 movl %esp, %ebp // frame pointer is the iframe 232 233 pushl %ebp 234 call x86_double_fault_exception 235 236 // Well, there's no returning from a double fault, but maybe a real hacker 237 // can repair things in KDL. 238 POP_IFRAME_AND_RETURN() 239FUNCTION_END(double_fault) 240 241 242TRAP(trap9, 9) 243TRAP_ERRC(trap10, 10) 244TRAP_ERRC(trap11, 11) 245TRAP_ERRC(trap12, 12) 246TRAP_ERRC(trap13, 13) 247TRAP_ERRC(trap14, 14) 248/*TRAP(trap15, 15)*/ 249TRAP(trap16, 16) 250TRAP_ERRC(trap17, 17) 251TRAP(trap18, 18) 252TRAP(trap19, 19) 253 254// legacy or ioapic interrupts 255TRAP(trap32, 32) 256TRAP(trap33, 33) 257TRAP(trap34, 34) 258TRAP(trap35, 35) 259TRAP(trap36, 36) 260TRAP(trap37, 37) 261TRAP(trap38, 38) 262TRAP(trap39, 39) 263TRAP(trap40, 40) 264TRAP(trap41, 41) 265TRAP(trap42, 42) 266TRAP(trap43, 43) 267TRAP(trap44, 44) 268TRAP(trap45, 45) 269TRAP(trap46, 46) 270TRAP(trap47, 47) 271 272// additional ioapic interrupts 273TRAP(trap48, 48) 274TRAP(trap49, 49) 275TRAP(trap50, 50) 276TRAP(trap51, 51) 277TRAP(trap52, 52) 278TRAP(trap53, 53) 279TRAP(trap54, 54) 280TRAP(trap55, 55) 281 282// configurable msi or msi-x interrupts 283TRAP(trap56, 56) 284TRAP(trap57, 57) 285TRAP(trap58, 58) 286TRAP(trap59, 59) 287TRAP(trap60, 60) 288TRAP(trap61, 61) 289TRAP(trap62, 62) 290TRAP(trap63, 63) 291TRAP(trap64, 64) 292TRAP(trap65, 65) 293TRAP(trap66, 66) 294TRAP(trap67, 67) 295TRAP(trap68, 68) 296TRAP(trap69, 69) 297TRAP(trap70, 70) 298TRAP(trap71, 71) 299TRAP(trap72, 72) 300TRAP(trap73, 73) 301TRAP(trap74, 74) 302TRAP(trap75, 75) 303TRAP(trap76, 76) 304TRAP(trap77, 77) 305TRAP(trap78, 78) 306TRAP(trap79, 79) 307TRAP(trap80, 80) 308TRAP(trap81, 81) 309TRAP(trap82, 82) 310TRAP(trap83, 83) 311TRAP(trap84, 84) 312TRAP(trap85, 85) 313TRAP(trap86, 86) 314TRAP(trap87, 87) 315TRAP(trap88, 88) 316TRAP(trap89, 89) 317TRAP(trap90, 90) 318TRAP(trap91, 91) 319TRAP(trap92, 92) 320TRAP(trap93, 93) 321TRAP(trap94, 94) 322TRAP(trap95, 95) 323TRAP(trap96, 96) 324TRAP(trap97, 97) 325//TRAP(trap98, 98) // performance testing interrupt 326//TRAP(trap99, 99) // syscall interrupt 327TRAP(trap100, 100) 328TRAP(trap101, 101) 329TRAP(trap102, 102) 330TRAP(trap103, 103) 331TRAP(trap104, 104) 332TRAP(trap105, 105) 333TRAP(trap106, 106) 334TRAP(trap107, 107) 335TRAP(trap108, 108) 336TRAP(trap109, 109) 337TRAP(trap110, 110) 338TRAP(trap111, 111) 339TRAP(trap112, 112) 340TRAP(trap113, 113) 341TRAP(trap114, 114) 342TRAP(trap115, 115) 343TRAP(trap116, 116) 344TRAP(trap117, 117) 345TRAP(trap118, 118) 346TRAP(trap119, 119) 347TRAP(trap120, 120) 348TRAP(trap121, 121) 349TRAP(trap122, 122) 350TRAP(trap123, 123) 351TRAP(trap124, 124) 352TRAP(trap125, 125) 353TRAP(trap126, 126) 354TRAP(trap127, 127) 355TRAP(trap128, 128) 356TRAP(trap129, 129) 357TRAP(trap130, 130) 358TRAP(trap131, 131) 359TRAP(trap132, 132) 360TRAP(trap133, 133) 361TRAP(trap134, 134) 362TRAP(trap135, 135) 363TRAP(trap136, 136) 364TRAP(trap137, 137) 365TRAP(trap138, 138) 366TRAP(trap139, 139) 367TRAP(trap140, 140) 368TRAP(trap141, 141) 369TRAP(trap142, 142) 370TRAP(trap143, 143) 371TRAP(trap144, 144) 372TRAP(trap145, 145) 373TRAP(trap146, 146) 374TRAP(trap147, 147) 375TRAP(trap148, 148) 376TRAP(trap149, 149) 377TRAP(trap150, 150) 378TRAP(trap151, 151) 379TRAP(trap152, 152) 380TRAP(trap153, 153) 381TRAP(trap154, 154) 382TRAP(trap155, 155) 383TRAP(trap156, 156) 384TRAP(trap157, 157) 385TRAP(trap158, 158) 386TRAP(trap159, 159) 387TRAP(trap160, 160) 388TRAP(trap161, 161) 389TRAP(trap162, 162) 390TRAP(trap163, 163) 391TRAP(trap164, 164) 392TRAP(trap165, 165) 393TRAP(trap166, 166) 394TRAP(trap167, 167) 395TRAP(trap168, 168) 396TRAP(trap169, 169) 397TRAP(trap170, 170) 398TRAP(trap171, 171) 399TRAP(trap172, 172) 400TRAP(trap173, 173) 401TRAP(trap174, 174) 402TRAP(trap175, 175) 403TRAP(trap176, 176) 404TRAP(trap177, 177) 405TRAP(trap178, 178) 406TRAP(trap179, 179) 407TRAP(trap180, 180) 408TRAP(trap181, 181) 409TRAP(trap182, 182) 410TRAP(trap183, 183) 411TRAP(trap184, 184) 412TRAP(trap185, 185) 413TRAP(trap186, 186) 414TRAP(trap187, 187) 415TRAP(trap188, 188) 416TRAP(trap189, 189) 417TRAP(trap190, 190) 418TRAP(trap191, 191) 419TRAP(trap192, 192) 420TRAP(trap193, 193) 421TRAP(trap194, 194) 422TRAP(trap195, 195) 423TRAP(trap196, 196) 424TRAP(trap197, 197) 425TRAP(trap198, 198) 426TRAP(trap199, 199) 427TRAP(trap200, 200) 428TRAP(trap201, 201) 429TRAP(trap202, 202) 430TRAP(trap203, 203) 431TRAP(trap204, 204) 432TRAP(trap205, 205) 433TRAP(trap206, 206) 434TRAP(trap207, 207) 435TRAP(trap208, 208) 436TRAP(trap209, 209) 437TRAP(trap210, 210) 438TRAP(trap211, 211) 439TRAP(trap212, 212) 440TRAP(trap213, 213) 441TRAP(trap214, 214) 442TRAP(trap215, 215) 443TRAP(trap216, 216) 444TRAP(trap217, 217) 445TRAP(trap218, 218) 446TRAP(trap219, 219) 447TRAP(trap220, 220) 448TRAP(trap221, 221) 449TRAP(trap222, 222) 450TRAP(trap223, 223) 451TRAP(trap224, 224) 452TRAP(trap225, 225) 453TRAP(trap226, 226) 454TRAP(trap227, 227) 455TRAP(trap228, 228) 456TRAP(trap229, 229) 457TRAP(trap230, 230) 458TRAP(trap231, 231) 459TRAP(trap232, 232) 460TRAP(trap233, 233) 461TRAP(trap234, 234) 462TRAP(trap235, 235) 463TRAP(trap236, 236) 464TRAP(trap237, 237) 465TRAP(trap238, 238) 466TRAP(trap239, 239) 467TRAP(trap240, 240) 468TRAP(trap241, 241) 469TRAP(trap242, 242) 470TRAP(trap243, 243) 471TRAP(trap244, 244) 472TRAP(trap245, 245) 473TRAP(trap246, 246) 474TRAP(trap247, 247) 475TRAP(trap248, 248) 476TRAP(trap249, 249) 477TRAP(trap250, 250) 478 479// smp / apic local interrupts 480TRAP(trap251, 251) 481TRAP(trap252, 252) 482TRAP(trap253, 253) 483TRAP(trap254, 254) 484TRAP(trap255, 255) 485 486 487.align 8; 488FUNCTION(trap14_double_fault): 489 pushl $14 490 pushl $-1 491 pushl $-1 492 493 PUSH_IFRAME_BOTTOM(IFRAME_TYPE_OTHER) 494 495 movl %esp, %ebp // frame pointer is the iframe 496 497 pushl %ebp 498 call x86_page_fault_exception_double_fault 499 500 POP_IFRAME_AND_RETURN() 501FUNCTION_END(trap14_double_fault) 502 503 504.align 16 505STATIC_FUNCTION(int_bottom): 506 PUSH_IFRAME_BOTTOM(IFRAME_TYPE_OTHER) 507 508 movl $KERNEL_TLS_SELECTOR, %edx 509 movw %dx, %gs 510 511 movl %esp, %ebp // frame pointer is the iframe 512 513 // Set the RF (resume flag) in EFLAGS. This prevents an instruction 514 // breakpoint on the instruction we're returning to to trigger a debug 515 // exception. 516 orl $0x10000, IFRAME_flags(%ebp); 517 518 cmpw $USER_CODE_SELECTOR, IFRAME_cs(%ebp) // user mode 519 je int_bottom_user 520 521 // We need to recheck user mode using the thread's in_kernel flag, since 522 // sysexit introduces a raced condition: It doesn't reenable interrupts, 523 // so that we have to do it in the instruction before, thus opening a 524 // window for an interrupt while still being in the kernel, but having set 525 // up everything for userland already. 526 movl %gs:0, %edi // thread pointer 527 cmpb $0, THREAD_in_kernel(%edi) 528 je int_bottom_user 529 530 // disable interrupts -- the handler will enable them, if necessary 531 cli 532 533 pushl %ebp 534 movl IFRAME_vector(%ebp), %eax 535 call *gInterruptHandlerTable(, %eax, 4) 536 537 POP_IFRAME_AND_RETURN() 538FUNCTION_END(int_bottom) 539 540 541STATIC_FUNCTION(int_bottom_user): 542 movl $KERNEL_DATA_SELECTOR, %eax 543 cld 544 movl %eax,%ds 545 movl %eax,%es 546 547 // disable breakpoints, if installed 548 movl %gs:0, %edi // thread pointer 549 cli // disable interrupts 550 STOP_USER_DEBUGGING() 551 552 // update the thread's user time 553 UPDATE_THREAD_USER_TIME() 554 555 // leave interrupts disabled -- the handler will enable them, if 556 // necessary 557 558 pushl %ebp 559 movl IFRAME_vector(%ebp), %eax 560 call *gInterruptHandlerTable(, %eax, 4) 561 562 // Don't do any kernel exit work, if we actually came from the kernel (but 563 // were already/still prepared for userland), since the iframe in this case 564 // will be a kernel iframe and e.g. trying to set up a signal stack will not 565 // be a very healthy endeavor. 566 cmpw $USER_CODE_SELECTOR, IFRAME_cs(%ebp) 567 jne 1f 568 569 testl $(THREAD_FLAGS_DEBUGGER_INSTALLED | THREAD_FLAGS_SIGNALS_PENDING \ 570 | THREAD_FLAGS_DEBUG_THREAD | THREAD_FLAGS_BREAKPOINTS_DEFINED \ 571 | THREAD_FLAGS_TRAP_FOR_CORE_DUMP) \ 572 , THREAD_flags(%edi) 573 jnz kernel_exit_work 5741: 575 576 cli // disable interrupts 577 578 // update the thread's kernel time and return 579 UPDATE_THREAD_KERNEL_TIME() 580 POP_IFRAME_AND_RETURN() 581FUNCTION_END(int_bottom_user) 582 583 584// test interrupt handler for performance measurements 585.align 16 586FUNCTION(trap98): 587 iret 588FUNCTION_END(trap98) 589 590 591.align 16 592FUNCTION(trap99): 593 // push error, vector, orig_edx, orig_eax, and other registers 594 PUSH_IFRAME_BOTTOM_SYSCALL() 595 596 call handle_syscall 597 598 POP_IFRAME_AND_RETURN() 599FUNCTION_END(trap99) 600 601 602STATIC_FUNCTION(handle_syscall): 603 movl $KERNEL_TLS_SELECTOR, %edx 604 movw %dx, %gs 605 606 // save %eax, the number of the syscall 607 movl %eax, %esi 608 609 movl $KERNEL_DATA_SELECTOR, %eax 610 cld 611 movl %eax,%ds 612 movl %eax,%es 613 614 lea 4(%esp), %ebp // skipping the return address, the stack 615 // frame pointer is the iframe 616 movl %gs:0, %edi // thread pointer 617 618 // disable breakpoints, if installed 619 cli // disable interrupts 620 STOP_USER_DEBUGGING() 621 622 // update the thread's user time 623 UPDATE_THREAD_USER_TIME_PUSH_TIME() 624 // leave the time on the stack (needed for post syscall debugging) 625 626 sti // enable interrupts 627 628 cmp $SYSCALL_COUNT, %esi // check syscall number 629 jae bad_syscall_number 630 movl $kSyscallInfos, %eax // get syscall info 631 lea (%eax, %esi, SYSCALL_INFO_sizeof), %edx 632 633 // copy parameters onto this stack 634 COPY_SYSCALL_PARAMETERS() 635 636 // pre syscall debugging 637 TRACE_PRE_SYSCALL() 638 testl $THREAD_FLAGS_DEBUGGER_INSTALLED, THREAD_flags(%edi) 639 jnz do_pre_syscall_debug 640 pre_syscall_debug_done: 641 642 // call the syscall function 643 call *SYSCALL_INFO_function(%esi) 644 645 testl $THREAD_FLAGS_64_BIT_SYSCALL_RETURN, THREAD_flags(%edi) 646 jnz 1f 647 xor %edx, %edx 648 1: 649 650 // overwrite the values of %eax and %edx on the stack (the syscall return value) 651 movl %edx, IFRAME_dx(%ebp) 652 movl %eax, IFRAME_ax(%ebp) 653 654 TRACE_POST_SYSCALL() 655 656 testl $(THREAD_FLAGS_DEBUGGER_INSTALLED | THREAD_FLAGS_SIGNALS_PENDING \ 657 | THREAD_FLAGS_DEBUG_THREAD | THREAD_FLAGS_BREAKPOINTS_DEFINED \ 658 | THREAD_FLAGS_TRAP_FOR_CORE_DUMP \ 659 | THREAD_FLAGS_64_BIT_SYSCALL_RETURN \ 660 | THREAD_FLAGS_RESTART_SYSCALL | THREAD_FLAGS_SYSCALL_RESTARTED) \ 661 , THREAD_flags(%edi) 662 jnz post_syscall_work 663 664 cli // disable interrupts 665 666 // update the thread's kernel time 667 UPDATE_THREAD_KERNEL_TIME() 668 669 lea -4(%ebp), %esp // remove all parameters from the stack 670 671 ret 672FUNCTION_END(handle_syscall) 673 674 STATIC_FUNCTION(do_pre_syscall_debug): 675 movl %esp, %eax // syscall parameters 676 push %eax 677 movl IFRAME_orig_eax(%ebp), %eax // syscall number 678 push %eax 679 call user_debug_pre_syscall 680 addl $8, %esp 681 jmp pre_syscall_debug_done 682 FUNCTION_END(do_pre_syscall_debug) 683 684 STATIC_FUNCTION(post_syscall_work): 685 // clear the 64 bit return value and syscall restarted bits 686 testl $(THREAD_FLAGS_64_BIT_SYSCALL_RETURN \ 687 | THREAD_FLAGS_SYSCALL_RESTARTED), THREAD_flags(%edi) 688 jz 2f 689 1: 690 movl THREAD_flags(%edi), %eax 691 movl %eax, %edx 692 andl $~(THREAD_FLAGS_64_BIT_SYSCALL_RETURN \ 693 | THREAD_FLAGS_SYSCALL_RESTARTED), %edx 694 lock 695 cmpxchgl %edx, THREAD_flags(%edi) 696 jnz 1b 697 2: 698 699 // post syscall debugging 700 testl $THREAD_FLAGS_DEBUGGER_INSTALLED, THREAD_flags(%edi) 701 jz 1f 702 pushl -8(%ebp) // syscall start time 703 pushl -12(%ebp) 704 movl IFRAME_dx(%ebp), %edx // syscall return value 705 movl IFRAME_ax(%ebp), %eax 706 push %edx 707 push %eax 708 lea 16(%esp), %eax // syscall parameters 709 push %eax 710 movl IFRAME_orig_eax(%ebp), %eax // syscall number 711 push %eax 712 call user_debug_post_syscall 713 addl $24, %esp 714 1: 715 FUNCTION_END(post_syscall_work) 716 717 bad_syscall_number: 718 STATIC_FUNCTION(kernel_exit_work): 719 // if no signals are pending and the thread shall not be debugged or stopped 720 // for a core dump, we can use the quick kernel exit function 721 testl $(THREAD_FLAGS_SIGNALS_PENDING | THREAD_FLAGS_DEBUG_THREAD \ 722 | THREAD_FLAGS_TRAP_FOR_CORE_DUMP) \ 723 , THREAD_flags(%edi) 724 jnz kernel_exit_handle_signals 725 cli // disable interrupts 726 call thread_at_kernel_exit_no_signals 727 kernel_exit_work_done: 728 729 // syscall restart 730 // TODO: this only needs to be done for syscalls! 731 testl $THREAD_FLAGS_RESTART_SYSCALL, THREAD_flags(%edi) 732 jz 1f 733 push %ebp 734 call x86_restart_syscall 735 addl $4, %esp 736 1: 737 738 // install breakpoints, if defined 739 testl $THREAD_FLAGS_BREAKPOINTS_DEFINED, THREAD_flags(%edi) 740 jz 1f 741 push %ebp 742 call x86_init_user_debug_at_kernel_exit 743 1: 744 POP_IFRAME_AND_RETURN() 745 FUNCTION_END(kernel_exit_work) 746 747 STATIC_FUNCTION(kernel_exit_handle_signals): 748 // make sure interrupts are enabled (they are, when coming from a syscall 749 // but otherwise they might be disabled) 750 sti 751 call thread_at_kernel_exit // also disables interrupts 752 jmp kernel_exit_work_done 753 FUNCTION_END(kernel_exit_handle_signals) 754 755 STATIC_FUNCTION(bad_syscall_params): 756 // clear the fault handler and exit normally 757 movl %gs:0, %edi 758 movl $0, THREAD_fault_handler(%edi) 759 jmp kernel_exit_work 760 FUNCTION_END(bad_syscall_params) 761 762 763/*! Handler called by the sysenter instruction 764 ecx - user esp 765*/ 766FUNCTION(x86_sysenter): 767 // get the thread 768 push %gs 769 movl $KERNEL_TLS_SELECTOR, %edx 770 movw %dx, %gs 771 movl %gs:0, %edx 772 pop %gs 773 774 // push the iframe 775 pushl $USER_DATA_SELECTOR // user_ss 776 pushl %ecx // user_esp 777 pushfl // eflags 778 orl $(1 << 9), (%esp) // set the IF (interrupts) bit 779 pushl $USER_CODE_SELECTOR // user cs 780 781 // user_eip 782 movl THREAD_team(%edx), %edx 783 movl TEAM_commpage_address(%edx), %edx 784 addl 4 * COMMPAGE_ENTRY_X86_SYSCALL(%edx), %edx 785 addl $4, %edx // sysenter is at offset 2, 2 bytes long 786 pushl %edx 787 788 PUSH_IFRAME_BOTTOM_SYSCALL() 789 790 call handle_syscall 791 792 // pop the bottom of the iframe 793 lea 4(%ebp), %esp // skip iframe type 794 795 pop %gs 796 addl $4, %esp /* we skip %fs, as this contains the CPU 797 dependent TLS segment */ 798 pop %es 799 pop %ds 800 801 popa 802 803 // ecx already contains the user esp -- load edx with the return address 804 movl 16(%esp), %edx 805 806 // pop eflags, which also reenables interrupts 807 addl $24, %esp // skip, orig_eax/edx, vector, error_code, eip, cs 808 popfl 809 810 sysexit 811FUNCTION_END(x86_sysenter) 812 813 814/*! \fn void x86_return_to_userland(iframe* frame) 815 \brief Returns to the userland environment given by \a frame. 816 817 Before returning to userland all potentially necessary kernel exit work is 818 done. 819 820 \a frame must point to a location somewhere on the caller's stack (e.g. a 821 local variable). 822 The function must be called with interrupts disabled. 823 824 \param frame The iframe defining the userland environment. 825*/ 826FUNCTION(x86_return_to_userland): 827 // get the iframe* parameter 828 movl 4(%esp), %ebp 829 movl %ebp, %esp 830 831 // check, if any kernel exit work has to be done 832 movl %gs:0, %edi 833 testl $(THREAD_FLAGS_DEBUGGER_INSTALLED | THREAD_FLAGS_SIGNALS_PENDING \ 834 | THREAD_FLAGS_DEBUG_THREAD | THREAD_FLAGS_BREAKPOINTS_DEFINED \ 835 | THREAD_FLAGS_TRAP_FOR_CORE_DUMP) \ 836 , THREAD_flags(%edi) 837 jnz kernel_exit_work 838 839 // update the thread's kernel time and return 840 UPDATE_THREAD_KERNEL_TIME() 841 POP_IFRAME_AND_RETURN() 842FUNCTION_END(x86_return_to_userland) 843