diff options
Diffstat (limited to 'arch/x86/kernel/entry_64.S')
-rw-r--r-- | arch/x86/kernel/entry_64.S | 84 |
1 files changed, 27 insertions, 57 deletions
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S index b5c061f8f358..0697ff139837 100644 --- a/arch/x86/kernel/entry_64.S +++ b/arch/x86/kernel/entry_64.S | |||
@@ -155,11 +155,11 @@ GLOBAL(return_to_handler) | |||
155 | 155 | ||
156 | call ftrace_return_to_handler | 156 | call ftrace_return_to_handler |
157 | 157 | ||
158 | movq %rax, 16(%rsp) | 158 | movq %rax, %rdi |
159 | movq 8(%rsp), %rdx | 159 | movq 8(%rsp), %rdx |
160 | movq (%rsp), %rax | 160 | movq (%rsp), %rax |
161 | addq $16, %rsp | 161 | addq $24, %rsp |
162 | retq | 162 | jmp *%rdi |
163 | #endif | 163 | #endif |
164 | 164 | ||
165 | 165 | ||
@@ -803,6 +803,10 @@ END(interrupt) | |||
803 | call \func | 803 | call \func |
804 | .endm | 804 | .endm |
805 | 805 | ||
806 | /* | ||
807 | * Interrupt entry/exit should be protected against kprobes | ||
808 | */ | ||
809 | .pushsection .kprobes.text, "ax" | ||
806 | /* | 810 | /* |
807 | * The interrupt stubs push (~vector+0x80) onto the stack and | 811 | * The interrupt stubs push (~vector+0x80) onto the stack and |
808 | * then jump to common_interrupt. | 812 | * then jump to common_interrupt. |
@@ -941,6 +945,10 @@ ENTRY(retint_kernel) | |||
941 | 945 | ||
942 | CFI_ENDPROC | 946 | CFI_ENDPROC |
943 | END(common_interrupt) | 947 | END(common_interrupt) |
948 | /* | ||
949 | * End of kprobes section | ||
950 | */ | ||
951 | .popsection | ||
944 | 952 | ||
945 | /* | 953 | /* |
946 | * APIC interrupts. | 954 | * APIC interrupts. |
@@ -969,8 +977,8 @@ apicinterrupt UV_BAU_MESSAGE \ | |||
969 | #endif | 977 | #endif |
970 | apicinterrupt LOCAL_TIMER_VECTOR \ | 978 | apicinterrupt LOCAL_TIMER_VECTOR \ |
971 | apic_timer_interrupt smp_apic_timer_interrupt | 979 | apic_timer_interrupt smp_apic_timer_interrupt |
972 | apicinterrupt GENERIC_INTERRUPT_VECTOR \ | 980 | apicinterrupt X86_PLATFORM_IPI_VECTOR \ |
973 | generic_interrupt smp_generic_interrupt | 981 | x86_platform_ipi smp_x86_platform_ipi |
974 | 982 | ||
975 | #ifdef CONFIG_SMP | 983 | #ifdef CONFIG_SMP |
976 | apicinterrupt INVALIDATE_TLB_VECTOR_START+0 \ | 984 | apicinterrupt INVALIDATE_TLB_VECTOR_START+0 \ |
@@ -1068,10 +1076,10 @@ ENTRY(\sym) | |||
1068 | TRACE_IRQS_OFF | 1076 | TRACE_IRQS_OFF |
1069 | movq %rsp,%rdi /* pt_regs pointer */ | 1077 | movq %rsp,%rdi /* pt_regs pointer */ |
1070 | xorl %esi,%esi /* no error code */ | 1078 | xorl %esi,%esi /* no error code */ |
1071 | PER_CPU(init_tss, %rbp) | 1079 | PER_CPU(init_tss, %r12) |
1072 | subq $EXCEPTION_STKSZ, TSS_ist + (\ist - 1) * 8(%rbp) | 1080 | subq $EXCEPTION_STKSZ, TSS_ist + (\ist - 1) * 8(%r12) |
1073 | call \do_sym | 1081 | call \do_sym |
1074 | addq $EXCEPTION_STKSZ, TSS_ist + (\ist - 1) * 8(%rbp) | 1082 | addq $EXCEPTION_STKSZ, TSS_ist + (\ist - 1) * 8(%r12) |
1075 | jmp paranoid_exit /* %ebx: no swapgs flag */ | 1083 | jmp paranoid_exit /* %ebx: no swapgs flag */ |
1076 | CFI_ENDPROC | 1084 | CFI_ENDPROC |
1077 | END(\sym) | 1085 | END(\sym) |
@@ -1158,63 +1166,20 @@ bad_gs: | |||
1158 | jmp 2b | 1166 | jmp 2b |
1159 | .previous | 1167 | .previous |
1160 | 1168 | ||
1161 | /* | 1169 | ENTRY(kernel_thread_helper) |
1162 | * Create a kernel thread. | ||
1163 | * | ||
1164 | * C extern interface: | ||
1165 | * extern long kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) | ||
1166 | * | ||
1167 | * asm input arguments: | ||
1168 | * rdi: fn, rsi: arg, rdx: flags | ||
1169 | */ | ||
1170 | ENTRY(kernel_thread) | ||
1171 | CFI_STARTPROC | ||
1172 | FAKE_STACK_FRAME $child_rip | ||
1173 | SAVE_ALL | ||
1174 | |||
1175 | # rdi: flags, rsi: usp, rdx: will be &pt_regs | ||
1176 | movq %rdx,%rdi | ||
1177 | orq kernel_thread_flags(%rip),%rdi | ||
1178 | movq $-1, %rsi | ||
1179 | movq %rsp, %rdx | ||
1180 | |||
1181 | xorl %r8d,%r8d | ||
1182 | xorl %r9d,%r9d | ||
1183 | |||
1184 | # clone now | ||
1185 | call do_fork | ||
1186 | movq %rax,RAX(%rsp) | ||
1187 | xorl %edi,%edi | ||
1188 | |||
1189 | /* | ||
1190 | * It isn't worth to check for reschedule here, | ||
1191 | * so internally to the x86_64 port you can rely on kernel_thread() | ||
1192 | * not to reschedule the child before returning, this avoids the need | ||
1193 | * of hacks for example to fork off the per-CPU idle tasks. | ||
1194 | * [Hopefully no generic code relies on the reschedule -AK] | ||
1195 | */ | ||
1196 | RESTORE_ALL | ||
1197 | UNFAKE_STACK_FRAME | ||
1198 | ret | ||
1199 | CFI_ENDPROC | ||
1200 | END(kernel_thread) | ||
1201 | |||
1202 | ENTRY(child_rip) | ||
1203 | pushq $0 # fake return address | 1170 | pushq $0 # fake return address |
1204 | CFI_STARTPROC | 1171 | CFI_STARTPROC |
1205 | /* | 1172 | /* |
1206 | * Here we are in the child and the registers are set as they were | 1173 | * Here we are in the child and the registers are set as they were |
1207 | * at kernel_thread() invocation in the parent. | 1174 | * at kernel_thread() invocation in the parent. |
1208 | */ | 1175 | */ |
1209 | movq %rdi, %rax | 1176 | call *%rsi |
1210 | movq %rsi, %rdi | ||
1211 | call *%rax | ||
1212 | # exit | 1177 | # exit |
1213 | mov %eax, %edi | 1178 | mov %eax, %edi |
1214 | call do_exit | 1179 | call do_exit |
1215 | ud2 # padding for call trace | 1180 | ud2 # padding for call trace |
1216 | CFI_ENDPROC | 1181 | CFI_ENDPROC |
1217 | END(child_rip) | 1182 | END(kernel_thread_helper) |
1218 | 1183 | ||
1219 | /* | 1184 | /* |
1220 | * execve(). This function needs to use IRET, not SYSRET, to set up all state properly. | 1185 | * execve(). This function needs to use IRET, not SYSRET, to set up all state properly. |
@@ -1491,12 +1456,17 @@ error_kernelspace: | |||
1491 | leaq irq_return(%rip),%rcx | 1456 | leaq irq_return(%rip),%rcx |
1492 | cmpq %rcx,RIP+8(%rsp) | 1457 | cmpq %rcx,RIP+8(%rsp) |
1493 | je error_swapgs | 1458 | je error_swapgs |
1494 | movl %ecx,%ecx /* zero extend */ | 1459 | movl %ecx,%eax /* zero extend */ |
1495 | cmpq %rcx,RIP+8(%rsp) | 1460 | cmpq %rax,RIP+8(%rsp) |
1496 | je error_swapgs | 1461 | je bstep_iret |
1497 | cmpq $gs_change,RIP+8(%rsp) | 1462 | cmpq $gs_change,RIP+8(%rsp) |
1498 | je error_swapgs | 1463 | je error_swapgs |
1499 | jmp error_sti | 1464 | jmp error_sti |
1465 | |||
1466 | bstep_iret: | ||
1467 | /* Fix truncated RIP */ | ||
1468 | movq %rcx,RIP+8(%rsp) | ||
1469 | jmp error_swapgs | ||
1500 | END(error_entry) | 1470 | END(error_entry) |
1501 | 1471 | ||
1502 | 1472 | ||