diff options
Diffstat (limited to 'arch/x86_64/kernel/entry.S')
-rw-r--r-- | arch/x86_64/kernel/entry.S | 113 |
1 files changed, 86 insertions, 27 deletions
diff --git a/arch/x86_64/kernel/entry.S b/arch/x86_64/kernel/entry.S index 586b34c00c48..7290e72b9a34 100644 --- a/arch/x86_64/kernel/entry.S +++ b/arch/x86_64/kernel/entry.S | |||
@@ -154,6 +154,7 @@ rff_trace: | |||
154 | GET_THREAD_INFO(%rcx) | 154 | GET_THREAD_INFO(%rcx) |
155 | jmp rff_action | 155 | jmp rff_action |
156 | CFI_ENDPROC | 156 | CFI_ENDPROC |
157 | END(ret_from_fork) | ||
157 | 158 | ||
158 | /* | 159 | /* |
159 | * System call entry. Upto 6 arguments in registers are supported. | 160 | * System call entry. Upto 6 arguments in registers are supported. |
@@ -188,7 +189,7 @@ rff_trace: | |||
188 | 189 | ||
189 | ENTRY(system_call) | 190 | ENTRY(system_call) |
190 | CFI_STARTPROC simple | 191 | CFI_STARTPROC simple |
191 | CFI_DEF_CFA rsp,0 | 192 | CFI_DEF_CFA rsp,PDA_STACKOFFSET |
192 | CFI_REGISTER rip,rcx | 193 | CFI_REGISTER rip,rcx |
193 | /*CFI_REGISTER rflags,r11*/ | 194 | /*CFI_REGISTER rflags,r11*/ |
194 | swapgs | 195 | swapgs |
@@ -285,6 +286,7 @@ tracesys: | |||
285 | /* Use IRET because user could have changed frame */ | 286 | /* Use IRET because user could have changed frame */ |
286 | jmp int_ret_from_sys_call | 287 | jmp int_ret_from_sys_call |
287 | CFI_ENDPROC | 288 | CFI_ENDPROC |
289 | END(system_call) | ||
288 | 290 | ||
289 | /* | 291 | /* |
290 | * Syscall return path ending with IRET. | 292 | * Syscall return path ending with IRET. |
@@ -364,6 +366,7 @@ int_restore_rest: | |||
364 | cli | 366 | cli |
365 | jmp int_with_check | 367 | jmp int_with_check |
366 | CFI_ENDPROC | 368 | CFI_ENDPROC |
369 | END(int_ret_from_sys_call) | ||
367 | 370 | ||
368 | /* | 371 | /* |
369 | * Certain special system calls that need to save a complete full stack frame. | 372 | * Certain special system calls that need to save a complete full stack frame. |
@@ -375,6 +378,7 @@ int_restore_rest: | |||
375 | leaq \func(%rip),%rax | 378 | leaq \func(%rip),%rax |
376 | leaq -ARGOFFSET+8(%rsp),\arg /* 8 for return address */ | 379 | leaq -ARGOFFSET+8(%rsp),\arg /* 8 for return address */ |
377 | jmp ptregscall_common | 380 | jmp ptregscall_common |
381 | END(\label) | ||
378 | .endm | 382 | .endm |
379 | 383 | ||
380 | CFI_STARTPROC | 384 | CFI_STARTPROC |
@@ -404,6 +408,7 @@ ENTRY(ptregscall_common) | |||
404 | CFI_REL_OFFSET rip, 0 | 408 | CFI_REL_OFFSET rip, 0 |
405 | ret | 409 | ret |
406 | CFI_ENDPROC | 410 | CFI_ENDPROC |
411 | END(ptregscall_common) | ||
407 | 412 | ||
408 | ENTRY(stub_execve) | 413 | ENTRY(stub_execve) |
409 | CFI_STARTPROC | 414 | CFI_STARTPROC |
@@ -418,6 +423,7 @@ ENTRY(stub_execve) | |||
418 | RESTORE_REST | 423 | RESTORE_REST |
419 | jmp int_ret_from_sys_call | 424 | jmp int_ret_from_sys_call |
420 | CFI_ENDPROC | 425 | CFI_ENDPROC |
426 | END(stub_execve) | ||
421 | 427 | ||
422 | /* | 428 | /* |
423 | * sigreturn is special because it needs to restore all registers on return. | 429 | * sigreturn is special because it needs to restore all registers on return. |
@@ -435,6 +441,7 @@ ENTRY(stub_rt_sigreturn) | |||
435 | RESTORE_REST | 441 | RESTORE_REST |
436 | jmp int_ret_from_sys_call | 442 | jmp int_ret_from_sys_call |
437 | CFI_ENDPROC | 443 | CFI_ENDPROC |
444 | END(stub_rt_sigreturn) | ||
438 | 445 | ||
439 | /* | 446 | /* |
440 | * initial frame state for interrupts and exceptions | 447 | * initial frame state for interrupts and exceptions |
@@ -466,29 +473,18 @@ ENTRY(stub_rt_sigreturn) | |||
466 | /* 0(%rsp): interrupt number */ | 473 | /* 0(%rsp): interrupt number */ |
467 | .macro interrupt func | 474 | .macro interrupt func |
468 | cld | 475 | cld |
469 | #ifdef CONFIG_DEBUG_INFO | ||
470 | SAVE_ALL | ||
471 | movq %rsp,%rdi | ||
472 | /* | ||
473 | * Setup a stack frame pointer. This allows gdb to trace | ||
474 | * back to the original stack. | ||
475 | */ | ||
476 | movq %rsp,%rbp | ||
477 | CFI_DEF_CFA_REGISTER rbp | ||
478 | #else | ||
479 | SAVE_ARGS | 476 | SAVE_ARGS |
480 | leaq -ARGOFFSET(%rsp),%rdi # arg1 for handler | 477 | leaq -ARGOFFSET(%rsp),%rdi # arg1 for handler |
481 | #endif | 478 | pushq %rbp |
479 | CFI_ADJUST_CFA_OFFSET 8 | ||
480 | CFI_REL_OFFSET rbp, 0 | ||
481 | movq %rsp,%rbp | ||
482 | CFI_DEF_CFA_REGISTER rbp | ||
482 | testl $3,CS(%rdi) | 483 | testl $3,CS(%rdi) |
483 | je 1f | 484 | je 1f |
484 | swapgs | 485 | swapgs |
485 | 1: incl %gs:pda_irqcount # RED-PEN should check preempt count | 486 | 1: incl %gs:pda_irqcount # RED-PEN should check preempt count |
486 | movq %gs:pda_irqstackptr,%rax | 487 | cmoveq %gs:pda_irqstackptr,%rsp |
487 | cmoveq %rax,%rsp /*todo This needs CFI annotation! */ | ||
488 | pushq %rdi # save old stack | ||
489 | #ifndef CONFIG_DEBUG_INFO | ||
490 | CFI_ADJUST_CFA_OFFSET 8 | ||
491 | #endif | ||
492 | call \func | 488 | call \func |
493 | .endm | 489 | .endm |
494 | 490 | ||
@@ -497,17 +493,11 @@ ENTRY(common_interrupt) | |||
497 | interrupt do_IRQ | 493 | interrupt do_IRQ |
498 | /* 0(%rsp): oldrsp-ARGOFFSET */ | 494 | /* 0(%rsp): oldrsp-ARGOFFSET */ |
499 | ret_from_intr: | 495 | ret_from_intr: |
500 | popq %rdi | ||
501 | #ifndef CONFIG_DEBUG_INFO | ||
502 | CFI_ADJUST_CFA_OFFSET -8 | ||
503 | #endif | ||
504 | cli | 496 | cli |
505 | decl %gs:pda_irqcount | 497 | decl %gs:pda_irqcount |
506 | #ifdef CONFIG_DEBUG_INFO | 498 | leaveq |
507 | movq RBP(%rdi),%rbp | ||
508 | CFI_DEF_CFA_REGISTER rsp | 499 | CFI_DEF_CFA_REGISTER rsp |
509 | #endif | 500 | CFI_ADJUST_CFA_OFFSET -8 |
510 | leaq ARGOFFSET(%rdi),%rsp /*todo This needs CFI annotation! */ | ||
511 | exit_intr: | 501 | exit_intr: |
512 | GET_THREAD_INFO(%rcx) | 502 | GET_THREAD_INFO(%rcx) |
513 | testl $3,CS-ARGOFFSET(%rsp) | 503 | testl $3,CS-ARGOFFSET(%rsp) |
@@ -589,7 +579,9 @@ retint_kernel: | |||
589 | call preempt_schedule_irq | 579 | call preempt_schedule_irq |
590 | jmp exit_intr | 580 | jmp exit_intr |
591 | #endif | 581 | #endif |
582 | |||
592 | CFI_ENDPROC | 583 | CFI_ENDPROC |
584 | END(common_interrupt) | ||
593 | 585 | ||
594 | /* | 586 | /* |
595 | * APIC interrupts. | 587 | * APIC interrupts. |
@@ -605,17 +597,21 @@ retint_kernel: | |||
605 | 597 | ||
606 | ENTRY(thermal_interrupt) | 598 | ENTRY(thermal_interrupt) |
607 | apicinterrupt THERMAL_APIC_VECTOR,smp_thermal_interrupt | 599 | apicinterrupt THERMAL_APIC_VECTOR,smp_thermal_interrupt |
600 | END(thermal_interrupt) | ||
608 | 601 | ||
609 | ENTRY(threshold_interrupt) | 602 | ENTRY(threshold_interrupt) |
610 | apicinterrupt THRESHOLD_APIC_VECTOR,mce_threshold_interrupt | 603 | apicinterrupt THRESHOLD_APIC_VECTOR,mce_threshold_interrupt |
604 | END(threshold_interrupt) | ||
611 | 605 | ||
612 | #ifdef CONFIG_SMP | 606 | #ifdef CONFIG_SMP |
613 | ENTRY(reschedule_interrupt) | 607 | ENTRY(reschedule_interrupt) |
614 | apicinterrupt RESCHEDULE_VECTOR,smp_reschedule_interrupt | 608 | apicinterrupt RESCHEDULE_VECTOR,smp_reschedule_interrupt |
609 | END(reschedule_interrupt) | ||
615 | 610 | ||
616 | .macro INVALIDATE_ENTRY num | 611 | .macro INVALIDATE_ENTRY num |
617 | ENTRY(invalidate_interrupt\num) | 612 | ENTRY(invalidate_interrupt\num) |
618 | apicinterrupt INVALIDATE_TLB_VECTOR_START+\num,smp_invalidate_interrupt | 613 | apicinterrupt INVALIDATE_TLB_VECTOR_START+\num,smp_invalidate_interrupt |
614 | END(invalidate_interrupt\num) | ||
619 | .endm | 615 | .endm |
620 | 616 | ||
621 | INVALIDATE_ENTRY 0 | 617 | INVALIDATE_ENTRY 0 |
@@ -629,17 +625,21 @@ ENTRY(invalidate_interrupt\num) | |||
629 | 625 | ||
630 | ENTRY(call_function_interrupt) | 626 | ENTRY(call_function_interrupt) |
631 | apicinterrupt CALL_FUNCTION_VECTOR,smp_call_function_interrupt | 627 | apicinterrupt CALL_FUNCTION_VECTOR,smp_call_function_interrupt |
628 | END(call_function_interrupt) | ||
632 | #endif | 629 | #endif |
633 | 630 | ||
634 | #ifdef CONFIG_X86_LOCAL_APIC | 631 | #ifdef CONFIG_X86_LOCAL_APIC |
635 | ENTRY(apic_timer_interrupt) | 632 | ENTRY(apic_timer_interrupt) |
636 | apicinterrupt LOCAL_TIMER_VECTOR,smp_apic_timer_interrupt | 633 | apicinterrupt LOCAL_TIMER_VECTOR,smp_apic_timer_interrupt |
634 | END(apic_timer_interrupt) | ||
637 | 635 | ||
638 | ENTRY(error_interrupt) | 636 | ENTRY(error_interrupt) |
639 | apicinterrupt ERROR_APIC_VECTOR,smp_error_interrupt | 637 | apicinterrupt ERROR_APIC_VECTOR,smp_error_interrupt |
638 | END(error_interrupt) | ||
640 | 639 | ||
641 | ENTRY(spurious_interrupt) | 640 | ENTRY(spurious_interrupt) |
642 | apicinterrupt SPURIOUS_APIC_VECTOR,smp_spurious_interrupt | 641 | apicinterrupt SPURIOUS_APIC_VECTOR,smp_spurious_interrupt |
642 | END(spurious_interrupt) | ||
643 | #endif | 643 | #endif |
644 | 644 | ||
645 | /* | 645 | /* |
@@ -777,6 +777,7 @@ error_kernelspace: | |||
777 | cmpq $gs_change,RIP(%rsp) | 777 | cmpq $gs_change,RIP(%rsp) |
778 | je error_swapgs | 778 | je error_swapgs |
779 | jmp error_sti | 779 | jmp error_sti |
780 | END(error_entry) | ||
780 | 781 | ||
781 | /* Reload gs selector with exception handling */ | 782 | /* Reload gs selector with exception handling */ |
782 | /* edi: new selector */ | 783 | /* edi: new selector */ |
@@ -794,6 +795,7 @@ gs_change: | |||
794 | CFI_ADJUST_CFA_OFFSET -8 | 795 | CFI_ADJUST_CFA_OFFSET -8 |
795 | ret | 796 | ret |
796 | CFI_ENDPROC | 797 | CFI_ENDPROC |
798 | ENDPROC(load_gs_index) | ||
797 | 799 | ||
798 | .section __ex_table,"a" | 800 | .section __ex_table,"a" |
799 | .align 8 | 801 | .align 8 |
@@ -847,7 +849,7 @@ ENTRY(kernel_thread) | |||
847 | UNFAKE_STACK_FRAME | 849 | UNFAKE_STACK_FRAME |
848 | ret | 850 | ret |
849 | CFI_ENDPROC | 851 | CFI_ENDPROC |
850 | 852 | ENDPROC(kernel_thread) | |
851 | 853 | ||
852 | child_rip: | 854 | child_rip: |
853 | /* | 855 | /* |
@@ -860,6 +862,7 @@ child_rip: | |||
860 | # exit | 862 | # exit |
861 | xorl %edi, %edi | 863 | xorl %edi, %edi |
862 | call do_exit | 864 | call do_exit |
865 | ENDPROC(child_rip) | ||
863 | 866 | ||
864 | /* | 867 | /* |
865 | * execve(). This function needs to use IRET, not SYSRET, to set up all state properly. | 868 | * execve(). This function needs to use IRET, not SYSRET, to set up all state properly. |
@@ -889,19 +892,24 @@ ENTRY(execve) | |||
889 | UNFAKE_STACK_FRAME | 892 | UNFAKE_STACK_FRAME |
890 | ret | 893 | ret |
891 | CFI_ENDPROC | 894 | CFI_ENDPROC |
895 | ENDPROC(execve) | ||
892 | 896 | ||
893 | KPROBE_ENTRY(page_fault) | 897 | KPROBE_ENTRY(page_fault) |
894 | errorentry do_page_fault | 898 | errorentry do_page_fault |
899 | END(page_fault) | ||
895 | .previous .text | 900 | .previous .text |
896 | 901 | ||
897 | ENTRY(coprocessor_error) | 902 | ENTRY(coprocessor_error) |
898 | zeroentry do_coprocessor_error | 903 | zeroentry do_coprocessor_error |
904 | END(coprocessor_error) | ||
899 | 905 | ||
900 | ENTRY(simd_coprocessor_error) | 906 | ENTRY(simd_coprocessor_error) |
901 | zeroentry do_simd_coprocessor_error | 907 | zeroentry do_simd_coprocessor_error |
908 | END(simd_coprocessor_error) | ||
902 | 909 | ||
903 | ENTRY(device_not_available) | 910 | ENTRY(device_not_available) |
904 | zeroentry math_state_restore | 911 | zeroentry math_state_restore |
912 | END(device_not_available) | ||
905 | 913 | ||
906 | /* runs on exception stack */ | 914 | /* runs on exception stack */ |
907 | KPROBE_ENTRY(debug) | 915 | KPROBE_ENTRY(debug) |
@@ -911,6 +919,7 @@ KPROBE_ENTRY(debug) | |||
911 | paranoidentry do_debug, DEBUG_STACK | 919 | paranoidentry do_debug, DEBUG_STACK |
912 | jmp paranoid_exit | 920 | jmp paranoid_exit |
913 | CFI_ENDPROC | 921 | CFI_ENDPROC |
922 | END(debug) | ||
914 | .previous .text | 923 | .previous .text |
915 | 924 | ||
916 | /* runs on exception stack */ | 925 | /* runs on exception stack */ |
@@ -961,6 +970,7 @@ paranoid_schedule: | |||
961 | cli | 970 | cli |
962 | jmp paranoid_userspace | 971 | jmp paranoid_userspace |
963 | CFI_ENDPROC | 972 | CFI_ENDPROC |
973 | END(nmi) | ||
964 | .previous .text | 974 | .previous .text |
965 | 975 | ||
966 | KPROBE_ENTRY(int3) | 976 | KPROBE_ENTRY(int3) |
@@ -970,22 +980,28 @@ KPROBE_ENTRY(int3) | |||
970 | paranoidentry do_int3, DEBUG_STACK | 980 | paranoidentry do_int3, DEBUG_STACK |
971 | jmp paranoid_exit | 981 | jmp paranoid_exit |
972 | CFI_ENDPROC | 982 | CFI_ENDPROC |
983 | END(int3) | ||
973 | .previous .text | 984 | .previous .text |
974 | 985 | ||
975 | ENTRY(overflow) | 986 | ENTRY(overflow) |
976 | zeroentry do_overflow | 987 | zeroentry do_overflow |
988 | END(overflow) | ||
977 | 989 | ||
978 | ENTRY(bounds) | 990 | ENTRY(bounds) |
979 | zeroentry do_bounds | 991 | zeroentry do_bounds |
992 | END(bounds) | ||
980 | 993 | ||
981 | ENTRY(invalid_op) | 994 | ENTRY(invalid_op) |
982 | zeroentry do_invalid_op | 995 | zeroentry do_invalid_op |
996 | END(invalid_op) | ||
983 | 997 | ||
984 | ENTRY(coprocessor_segment_overrun) | 998 | ENTRY(coprocessor_segment_overrun) |
985 | zeroentry do_coprocessor_segment_overrun | 999 | zeroentry do_coprocessor_segment_overrun |
1000 | END(coprocessor_segment_overrun) | ||
986 | 1001 | ||
987 | ENTRY(reserved) | 1002 | ENTRY(reserved) |
988 | zeroentry do_reserved | 1003 | zeroentry do_reserved |
1004 | END(reserved) | ||
989 | 1005 | ||
990 | /* runs on exception stack */ | 1006 | /* runs on exception stack */ |
991 | ENTRY(double_fault) | 1007 | ENTRY(double_fault) |
@@ -993,12 +1009,15 @@ ENTRY(double_fault) | |||
993 | paranoidentry do_double_fault | 1009 | paranoidentry do_double_fault |
994 | jmp paranoid_exit | 1010 | jmp paranoid_exit |
995 | CFI_ENDPROC | 1011 | CFI_ENDPROC |
1012 | END(double_fault) | ||
996 | 1013 | ||
997 | ENTRY(invalid_TSS) | 1014 | ENTRY(invalid_TSS) |
998 | errorentry do_invalid_TSS | 1015 | errorentry do_invalid_TSS |
1016 | END(invalid_TSS) | ||
999 | 1017 | ||
1000 | ENTRY(segment_not_present) | 1018 | ENTRY(segment_not_present) |
1001 | errorentry do_segment_not_present | 1019 | errorentry do_segment_not_present |
1020 | END(segment_not_present) | ||
1002 | 1021 | ||
1003 | /* runs on exception stack */ | 1022 | /* runs on exception stack */ |
1004 | ENTRY(stack_segment) | 1023 | ENTRY(stack_segment) |
@@ -1006,19 +1025,24 @@ ENTRY(stack_segment) | |||
1006 | paranoidentry do_stack_segment | 1025 | paranoidentry do_stack_segment |
1007 | jmp paranoid_exit | 1026 | jmp paranoid_exit |
1008 | CFI_ENDPROC | 1027 | CFI_ENDPROC |
1028 | END(stack_segment) | ||
1009 | 1029 | ||
1010 | KPROBE_ENTRY(general_protection) | 1030 | KPROBE_ENTRY(general_protection) |
1011 | errorentry do_general_protection | 1031 | errorentry do_general_protection |
1032 | END(general_protection) | ||
1012 | .previous .text | 1033 | .previous .text |
1013 | 1034 | ||
1014 | ENTRY(alignment_check) | 1035 | ENTRY(alignment_check) |
1015 | errorentry do_alignment_check | 1036 | errorentry do_alignment_check |
1037 | END(alignment_check) | ||
1016 | 1038 | ||
1017 | ENTRY(divide_error) | 1039 | ENTRY(divide_error) |
1018 | zeroentry do_divide_error | 1040 | zeroentry do_divide_error |
1041 | END(divide_error) | ||
1019 | 1042 | ||
1020 | ENTRY(spurious_interrupt_bug) | 1043 | ENTRY(spurious_interrupt_bug) |
1021 | zeroentry do_spurious_interrupt_bug | 1044 | zeroentry do_spurious_interrupt_bug |
1045 | END(spurious_interrupt_bug) | ||
1022 | 1046 | ||
1023 | #ifdef CONFIG_X86_MCE | 1047 | #ifdef CONFIG_X86_MCE |
1024 | /* runs on exception stack */ | 1048 | /* runs on exception stack */ |
@@ -1029,6 +1053,7 @@ ENTRY(machine_check) | |||
1029 | paranoidentry do_machine_check | 1053 | paranoidentry do_machine_check |
1030 | jmp paranoid_exit | 1054 | jmp paranoid_exit |
1031 | CFI_ENDPROC | 1055 | CFI_ENDPROC |
1056 | END(machine_check) | ||
1032 | #endif | 1057 | #endif |
1033 | 1058 | ||
1034 | ENTRY(call_softirq) | 1059 | ENTRY(call_softirq) |
@@ -1046,3 +1071,37 @@ ENTRY(call_softirq) | |||
1046 | decl %gs:pda_irqcount | 1071 | decl %gs:pda_irqcount |
1047 | ret | 1072 | ret |
1048 | CFI_ENDPROC | 1073 | CFI_ENDPROC |
1074 | ENDPROC(call_softirq) | ||
1075 | |||
1076 | #ifdef CONFIG_STACK_UNWIND | ||
1077 | ENTRY(arch_unwind_init_running) | ||
1078 | CFI_STARTPROC | ||
1079 | movq %r15, R15(%rdi) | ||
1080 | movq %r14, R14(%rdi) | ||
1081 | xchgq %rsi, %rdx | ||
1082 | movq %r13, R13(%rdi) | ||
1083 | movq %r12, R12(%rdi) | ||
1084 | xorl %eax, %eax | ||
1085 | movq %rbp, RBP(%rdi) | ||
1086 | movq %rbx, RBX(%rdi) | ||
1087 | movq (%rsp), %rcx | ||
1088 | movq %rax, R11(%rdi) | ||
1089 | movq %rax, R10(%rdi) | ||
1090 | movq %rax, R9(%rdi) | ||
1091 | movq %rax, R8(%rdi) | ||
1092 | movq %rax, RAX(%rdi) | ||
1093 | movq %rax, RCX(%rdi) | ||
1094 | movq %rax, RDX(%rdi) | ||
1095 | movq %rax, RSI(%rdi) | ||
1096 | movq %rax, RDI(%rdi) | ||
1097 | movq %rax, ORIG_RAX(%rdi) | ||
1098 | movq %rcx, RIP(%rdi) | ||
1099 | leaq 8(%rsp), %rcx | ||
1100 | movq $__KERNEL_CS, CS(%rdi) | ||
1101 | movq %rax, EFLAGS(%rdi) | ||
1102 | movq %rcx, RSP(%rdi) | ||
1103 | movq $__KERNEL_DS, SS(%rdi) | ||
1104 | jmpq *%rdx | ||
1105 | CFI_ENDPROC | ||
1106 | ENDPROC(arch_unwind_init_running) | ||
1107 | #endif | ||