diff options
Diffstat (limited to 'arch/x86/kernel/entry_32.S')
-rw-r--r-- | arch/x86/kernel/entry_32.S | 100 |
1 files changed, 96 insertions, 4 deletions
diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S index 623f28837476..0750e3ba87c0 100644 --- a/arch/x86/kernel/entry_32.S +++ b/arch/x86/kernel/entry_32.S | |||
@@ -57,6 +57,7 @@ | |||
57 | #include <asm/cpufeature.h> | 57 | #include <asm/cpufeature.h> |
58 | #include <asm/alternative-asm.h> | 58 | #include <asm/alternative-asm.h> |
59 | #include <asm/asm.h> | 59 | #include <asm/asm.h> |
60 | #include <asm/smap.h> | ||
60 | 61 | ||
61 | /* Avoid __ASSEMBLER__'ifying <linux/audit.h> just for this. */ | 62 | /* Avoid __ASSEMBLER__'ifying <linux/audit.h> just for this. */ |
62 | #include <linux/elf-em.h> | 63 | #include <linux/elf-em.h> |
@@ -407,7 +408,9 @@ sysenter_past_esp: | |||
407 | */ | 408 | */ |
408 | cmpl $__PAGE_OFFSET-3,%ebp | 409 | cmpl $__PAGE_OFFSET-3,%ebp |
409 | jae syscall_fault | 410 | jae syscall_fault |
411 | ASM_STAC | ||
410 | 1: movl (%ebp),%ebp | 412 | 1: movl (%ebp),%ebp |
413 | ASM_CLAC | ||
411 | movl %ebp,PT_EBP(%esp) | 414 | movl %ebp,PT_EBP(%esp) |
412 | _ASM_EXTABLE(1b,syscall_fault) | 415 | _ASM_EXTABLE(1b,syscall_fault) |
413 | 416 | ||
@@ -488,6 +491,7 @@ ENDPROC(ia32_sysenter_target) | |||
488 | # system call handler stub | 491 | # system call handler stub |
489 | ENTRY(system_call) | 492 | ENTRY(system_call) |
490 | RING0_INT_FRAME # can't unwind into user space anyway | 493 | RING0_INT_FRAME # can't unwind into user space anyway |
494 | ASM_CLAC | ||
491 | pushl_cfi %eax # save orig_eax | 495 | pushl_cfi %eax # save orig_eax |
492 | SAVE_ALL | 496 | SAVE_ALL |
493 | GET_THREAD_INFO(%ebp) | 497 | GET_THREAD_INFO(%ebp) |
@@ -670,6 +674,7 @@ END(syscall_exit_work) | |||
670 | 674 | ||
671 | RING0_INT_FRAME # can't unwind into user space anyway | 675 | RING0_INT_FRAME # can't unwind into user space anyway |
672 | syscall_fault: | 676 | syscall_fault: |
677 | ASM_CLAC | ||
673 | GET_THREAD_INFO(%ebp) | 678 | GET_THREAD_INFO(%ebp) |
674 | movl $-EFAULT,PT_EAX(%esp) | 679 | movl $-EFAULT,PT_EAX(%esp) |
675 | jmp resume_userspace | 680 | jmp resume_userspace |
@@ -825,6 +830,7 @@ END(interrupt) | |||
825 | */ | 830 | */ |
826 | .p2align CONFIG_X86_L1_CACHE_SHIFT | 831 | .p2align CONFIG_X86_L1_CACHE_SHIFT |
827 | common_interrupt: | 832 | common_interrupt: |
833 | ASM_CLAC | ||
828 | addl $-0x80,(%esp) /* Adjust vector into the [-256,-1] range */ | 834 | addl $-0x80,(%esp) /* Adjust vector into the [-256,-1] range */ |
829 | SAVE_ALL | 835 | SAVE_ALL |
830 | TRACE_IRQS_OFF | 836 | TRACE_IRQS_OFF |
@@ -841,6 +847,7 @@ ENDPROC(common_interrupt) | |||
841 | #define BUILD_INTERRUPT3(name, nr, fn) \ | 847 | #define BUILD_INTERRUPT3(name, nr, fn) \ |
842 | ENTRY(name) \ | 848 | ENTRY(name) \ |
843 | RING0_INT_FRAME; \ | 849 | RING0_INT_FRAME; \ |
850 | ASM_CLAC; \ | ||
844 | pushl_cfi $~(nr); \ | 851 | pushl_cfi $~(nr); \ |
845 | SAVE_ALL; \ | 852 | SAVE_ALL; \ |
846 | TRACE_IRQS_OFF \ | 853 | TRACE_IRQS_OFF \ |
@@ -857,6 +864,7 @@ ENDPROC(name) | |||
857 | 864 | ||
858 | ENTRY(coprocessor_error) | 865 | ENTRY(coprocessor_error) |
859 | RING0_INT_FRAME | 866 | RING0_INT_FRAME |
867 | ASM_CLAC | ||
860 | pushl_cfi $0 | 868 | pushl_cfi $0 |
861 | pushl_cfi $do_coprocessor_error | 869 | pushl_cfi $do_coprocessor_error |
862 | jmp error_code | 870 | jmp error_code |
@@ -865,6 +873,7 @@ END(coprocessor_error) | |||
865 | 873 | ||
866 | ENTRY(simd_coprocessor_error) | 874 | ENTRY(simd_coprocessor_error) |
867 | RING0_INT_FRAME | 875 | RING0_INT_FRAME |
876 | ASM_CLAC | ||
868 | pushl_cfi $0 | 877 | pushl_cfi $0 |
869 | #ifdef CONFIG_X86_INVD_BUG | 878 | #ifdef CONFIG_X86_INVD_BUG |
870 | /* AMD 486 bug: invd from userspace calls exception 19 instead of #GP */ | 879 | /* AMD 486 bug: invd from userspace calls exception 19 instead of #GP */ |
@@ -886,6 +895,7 @@ END(simd_coprocessor_error) | |||
886 | 895 | ||
887 | ENTRY(device_not_available) | 896 | ENTRY(device_not_available) |
888 | RING0_INT_FRAME | 897 | RING0_INT_FRAME |
898 | ASM_CLAC | ||
889 | pushl_cfi $-1 # mark this as an int | 899 | pushl_cfi $-1 # mark this as an int |
890 | pushl_cfi $do_device_not_available | 900 | pushl_cfi $do_device_not_available |
891 | jmp error_code | 901 | jmp error_code |
@@ -906,6 +916,7 @@ END(native_irq_enable_sysexit) | |||
906 | 916 | ||
907 | ENTRY(overflow) | 917 | ENTRY(overflow) |
908 | RING0_INT_FRAME | 918 | RING0_INT_FRAME |
919 | ASM_CLAC | ||
909 | pushl_cfi $0 | 920 | pushl_cfi $0 |
910 | pushl_cfi $do_overflow | 921 | pushl_cfi $do_overflow |
911 | jmp error_code | 922 | jmp error_code |
@@ -914,6 +925,7 @@ END(overflow) | |||
914 | 925 | ||
915 | ENTRY(bounds) | 926 | ENTRY(bounds) |
916 | RING0_INT_FRAME | 927 | RING0_INT_FRAME |
928 | ASM_CLAC | ||
917 | pushl_cfi $0 | 929 | pushl_cfi $0 |
918 | pushl_cfi $do_bounds | 930 | pushl_cfi $do_bounds |
919 | jmp error_code | 931 | jmp error_code |
@@ -922,6 +934,7 @@ END(bounds) | |||
922 | 934 | ||
923 | ENTRY(invalid_op) | 935 | ENTRY(invalid_op) |
924 | RING0_INT_FRAME | 936 | RING0_INT_FRAME |
937 | ASM_CLAC | ||
925 | pushl_cfi $0 | 938 | pushl_cfi $0 |
926 | pushl_cfi $do_invalid_op | 939 | pushl_cfi $do_invalid_op |
927 | jmp error_code | 940 | jmp error_code |
@@ -930,6 +943,7 @@ END(invalid_op) | |||
930 | 943 | ||
931 | ENTRY(coprocessor_segment_overrun) | 944 | ENTRY(coprocessor_segment_overrun) |
932 | RING0_INT_FRAME | 945 | RING0_INT_FRAME |
946 | ASM_CLAC | ||
933 | pushl_cfi $0 | 947 | pushl_cfi $0 |
934 | pushl_cfi $do_coprocessor_segment_overrun | 948 | pushl_cfi $do_coprocessor_segment_overrun |
935 | jmp error_code | 949 | jmp error_code |
@@ -938,6 +952,7 @@ END(coprocessor_segment_overrun) | |||
938 | 952 | ||
939 | ENTRY(invalid_TSS) | 953 | ENTRY(invalid_TSS) |
940 | RING0_EC_FRAME | 954 | RING0_EC_FRAME |
955 | ASM_CLAC | ||
941 | pushl_cfi $do_invalid_TSS | 956 | pushl_cfi $do_invalid_TSS |
942 | jmp error_code | 957 | jmp error_code |
943 | CFI_ENDPROC | 958 | CFI_ENDPROC |
@@ -945,6 +960,7 @@ END(invalid_TSS) | |||
945 | 960 | ||
946 | ENTRY(segment_not_present) | 961 | ENTRY(segment_not_present) |
947 | RING0_EC_FRAME | 962 | RING0_EC_FRAME |
963 | ASM_CLAC | ||
948 | pushl_cfi $do_segment_not_present | 964 | pushl_cfi $do_segment_not_present |
949 | jmp error_code | 965 | jmp error_code |
950 | CFI_ENDPROC | 966 | CFI_ENDPROC |
@@ -952,6 +968,7 @@ END(segment_not_present) | |||
952 | 968 | ||
953 | ENTRY(stack_segment) | 969 | ENTRY(stack_segment) |
954 | RING0_EC_FRAME | 970 | RING0_EC_FRAME |
971 | ASM_CLAC | ||
955 | pushl_cfi $do_stack_segment | 972 | pushl_cfi $do_stack_segment |
956 | jmp error_code | 973 | jmp error_code |
957 | CFI_ENDPROC | 974 | CFI_ENDPROC |
@@ -959,6 +976,7 @@ END(stack_segment) | |||
959 | 976 | ||
960 | ENTRY(alignment_check) | 977 | ENTRY(alignment_check) |
961 | RING0_EC_FRAME | 978 | RING0_EC_FRAME |
979 | ASM_CLAC | ||
962 | pushl_cfi $do_alignment_check | 980 | pushl_cfi $do_alignment_check |
963 | jmp error_code | 981 | jmp error_code |
964 | CFI_ENDPROC | 982 | CFI_ENDPROC |
@@ -966,6 +984,7 @@ END(alignment_check) | |||
966 | 984 | ||
967 | ENTRY(divide_error) | 985 | ENTRY(divide_error) |
968 | RING0_INT_FRAME | 986 | RING0_INT_FRAME |
987 | ASM_CLAC | ||
969 | pushl_cfi $0 # no error code | 988 | pushl_cfi $0 # no error code |
970 | pushl_cfi $do_divide_error | 989 | pushl_cfi $do_divide_error |
971 | jmp error_code | 990 | jmp error_code |
@@ -975,6 +994,7 @@ END(divide_error) | |||
975 | #ifdef CONFIG_X86_MCE | 994 | #ifdef CONFIG_X86_MCE |
976 | ENTRY(machine_check) | 995 | ENTRY(machine_check) |
977 | RING0_INT_FRAME | 996 | RING0_INT_FRAME |
997 | ASM_CLAC | ||
978 | pushl_cfi $0 | 998 | pushl_cfi $0 |
979 | pushl_cfi machine_check_vector | 999 | pushl_cfi machine_check_vector |
980 | jmp error_code | 1000 | jmp error_code |
@@ -984,6 +1004,7 @@ END(machine_check) | |||
984 | 1004 | ||
985 | ENTRY(spurious_interrupt_bug) | 1005 | ENTRY(spurious_interrupt_bug) |
986 | RING0_INT_FRAME | 1006 | RING0_INT_FRAME |
1007 | ASM_CLAC | ||
987 | pushl_cfi $0 | 1008 | pushl_cfi $0 |
988 | pushl_cfi $do_spurious_interrupt_bug | 1009 | pushl_cfi $do_spurious_interrupt_bug |
989 | jmp error_code | 1010 | jmp error_code |
@@ -1109,17 +1130,21 @@ ENTRY(ftrace_caller) | |||
1109 | pushl %eax | 1130 | pushl %eax |
1110 | pushl %ecx | 1131 | pushl %ecx |
1111 | pushl %edx | 1132 | pushl %edx |
1112 | movl 0xc(%esp), %eax | 1133 | pushl $0 /* Pass NULL as regs pointer */ |
1134 | movl 4*4(%esp), %eax | ||
1113 | movl 0x4(%ebp), %edx | 1135 | movl 0x4(%ebp), %edx |
1136 | leal function_trace_op, %ecx | ||
1114 | subl $MCOUNT_INSN_SIZE, %eax | 1137 | subl $MCOUNT_INSN_SIZE, %eax |
1115 | 1138 | ||
1116 | .globl ftrace_call | 1139 | .globl ftrace_call |
1117 | ftrace_call: | 1140 | ftrace_call: |
1118 | call ftrace_stub | 1141 | call ftrace_stub |
1119 | 1142 | ||
1143 | addl $4,%esp /* skip NULL pointer */ | ||
1120 | popl %edx | 1144 | popl %edx |
1121 | popl %ecx | 1145 | popl %ecx |
1122 | popl %eax | 1146 | popl %eax |
1147 | ftrace_ret: | ||
1123 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | 1148 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER |
1124 | .globl ftrace_graph_call | 1149 | .globl ftrace_graph_call |
1125 | ftrace_graph_call: | 1150 | ftrace_graph_call: |
@@ -1131,6 +1156,71 @@ ftrace_stub: | |||
1131 | ret | 1156 | ret |
1132 | END(ftrace_caller) | 1157 | END(ftrace_caller) |
1133 | 1158 | ||
1159 | ENTRY(ftrace_regs_caller) | ||
1160 | pushf /* push flags before compare (in cs location) */ | ||
1161 | cmpl $0, function_trace_stop | ||
1162 | jne ftrace_restore_flags | ||
1163 | |||
1164 | /* | ||
1165 | * i386 does not save SS and ESP when coming from kernel. | ||
1166 | * Instead, to get sp, ®s->sp is used (see ptrace.h). | ||
1167 | * Unfortunately, that means eflags must be at the same location | ||
1168 | * as the current return ip is. We move the return ip into the | ||
1169 | * ip location, and move flags into the return ip location. | ||
1170 | */ | ||
1171 | pushl 4(%esp) /* save return ip into ip slot */ | ||
1172 | |||
1173 | pushl $0 /* Load 0 into orig_ax */ | ||
1174 | pushl %gs | ||
1175 | pushl %fs | ||
1176 | pushl %es | ||
1177 | pushl %ds | ||
1178 | pushl %eax | ||
1179 | pushl %ebp | ||
1180 | pushl %edi | ||
1181 | pushl %esi | ||
1182 | pushl %edx | ||
1183 | pushl %ecx | ||
1184 | pushl %ebx | ||
1185 | |||
1186 | movl 13*4(%esp), %eax /* Get the saved flags */ | ||
1187 | movl %eax, 14*4(%esp) /* Move saved flags into regs->flags location */ | ||
1188 | /* clobbering return ip */ | ||
1189 | movl $__KERNEL_CS,13*4(%esp) | ||
1190 | |||
1191 | movl 12*4(%esp), %eax /* Load ip (1st parameter) */ | ||
1192 | subl $MCOUNT_INSN_SIZE, %eax /* Adjust ip */ | ||
1193 | movl 0x4(%ebp), %edx /* Load parent ip (2nd parameter) */ | ||
1194 | leal function_trace_op, %ecx /* Save ftrace_pos in 3rd parameter */ | ||
1195 | pushl %esp /* Save pt_regs as 4th parameter */ | ||
1196 | |||
1197 | GLOBAL(ftrace_regs_call) | ||
1198 | call ftrace_stub | ||
1199 | |||
1200 | addl $4, %esp /* Skip pt_regs */ | ||
1201 | movl 14*4(%esp), %eax /* Move flags back into cs */ | ||
1202 | movl %eax, 13*4(%esp) /* Needed to keep addl from modifying flags */ | ||
1203 | movl 12*4(%esp), %eax /* Get return ip from regs->ip */ | ||
1204 | movl %eax, 14*4(%esp) /* Put return ip back for ret */ | ||
1205 | |||
1206 | popl %ebx | ||
1207 | popl %ecx | ||
1208 | popl %edx | ||
1209 | popl %esi | ||
1210 | popl %edi | ||
1211 | popl %ebp | ||
1212 | popl %eax | ||
1213 | popl %ds | ||
1214 | popl %es | ||
1215 | popl %fs | ||
1216 | popl %gs | ||
1217 | addl $8, %esp /* Skip orig_ax and ip */ | ||
1218 | popf /* Pop flags at end (no addl to corrupt flags) */ | ||
1219 | jmp ftrace_ret | ||
1220 | |||
1221 | ftrace_restore_flags: | ||
1222 | popf | ||
1223 | jmp ftrace_stub | ||
1134 | #else /* ! CONFIG_DYNAMIC_FTRACE */ | 1224 | #else /* ! CONFIG_DYNAMIC_FTRACE */ |
1135 | 1225 | ||
1136 | ENTRY(mcount) | 1226 | ENTRY(mcount) |
@@ -1171,9 +1261,6 @@ END(mcount) | |||
1171 | 1261 | ||
1172 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | 1262 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER |
1173 | ENTRY(ftrace_graph_caller) | 1263 | ENTRY(ftrace_graph_caller) |
1174 | cmpl $0, function_trace_stop | ||
1175 | jne ftrace_stub | ||
1176 | |||
1177 | pushl %eax | 1264 | pushl %eax |
1178 | pushl %ecx | 1265 | pushl %ecx |
1179 | pushl %edx | 1266 | pushl %edx |
@@ -1207,6 +1294,7 @@ return_to_handler: | |||
1207 | 1294 | ||
1208 | ENTRY(page_fault) | 1295 | ENTRY(page_fault) |
1209 | RING0_EC_FRAME | 1296 | RING0_EC_FRAME |
1297 | ASM_CLAC | ||
1210 | pushl_cfi $do_page_fault | 1298 | pushl_cfi $do_page_fault |
1211 | ALIGN | 1299 | ALIGN |
1212 | error_code: | 1300 | error_code: |
@@ -1279,6 +1367,7 @@ END(page_fault) | |||
1279 | 1367 | ||
1280 | ENTRY(debug) | 1368 | ENTRY(debug) |
1281 | RING0_INT_FRAME | 1369 | RING0_INT_FRAME |
1370 | ASM_CLAC | ||
1282 | cmpl $ia32_sysenter_target,(%esp) | 1371 | cmpl $ia32_sysenter_target,(%esp) |
1283 | jne debug_stack_correct | 1372 | jne debug_stack_correct |
1284 | FIX_STACK 12, debug_stack_correct, debug_esp_fix_insn | 1373 | FIX_STACK 12, debug_stack_correct, debug_esp_fix_insn |
@@ -1303,6 +1392,7 @@ END(debug) | |||
1303 | */ | 1392 | */ |
1304 | ENTRY(nmi) | 1393 | ENTRY(nmi) |
1305 | RING0_INT_FRAME | 1394 | RING0_INT_FRAME |
1395 | ASM_CLAC | ||
1306 | pushl_cfi %eax | 1396 | pushl_cfi %eax |
1307 | movl %ss, %eax | 1397 | movl %ss, %eax |
1308 | cmpw $__ESPFIX_SS, %ax | 1398 | cmpw $__ESPFIX_SS, %ax |
@@ -1373,6 +1463,7 @@ END(nmi) | |||
1373 | 1463 | ||
1374 | ENTRY(int3) | 1464 | ENTRY(int3) |
1375 | RING0_INT_FRAME | 1465 | RING0_INT_FRAME |
1466 | ASM_CLAC | ||
1376 | pushl_cfi $-1 # mark this as an int | 1467 | pushl_cfi $-1 # mark this as an int |
1377 | SAVE_ALL | 1468 | SAVE_ALL |
1378 | TRACE_IRQS_OFF | 1469 | TRACE_IRQS_OFF |
@@ -1393,6 +1484,7 @@ END(general_protection) | |||
1393 | #ifdef CONFIG_KVM_GUEST | 1484 | #ifdef CONFIG_KVM_GUEST |
1394 | ENTRY(async_page_fault) | 1485 | ENTRY(async_page_fault) |
1395 | RING0_EC_FRAME | 1486 | RING0_EC_FRAME |
1487 | ASM_CLAC | ||
1396 | pushl_cfi $do_async_page_fault | 1488 | pushl_cfi $do_async_page_fault |
1397 | jmp error_code | 1489 | jmp error_code |
1398 | CFI_ENDPROC | 1490 | CFI_ENDPROC |