Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

x86/entry/64/compat: Migrate the body of the syscall entry to C

Signed-off-by: Andy Lutomirski <luto@kernel.org>
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Denys Vlasenko <dvlasenk@redhat.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: linux-kernel@vger.kernel.org
Link: http://lkml.kernel.org/r/a2f0fce68feeba798a24339b5a7ec1ec2dd9eaf7.1444091585.git.luto@kernel.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>

authored by

Andy Lutomirski and committed by
Ingo Molnar
ee08c6bd bd2d3a3b

+19 -39
+1 -1
arch/x86/entry/entry_64.S
··· 582 582 * At this label, code paths which return to kernel and to user, 583 583 * which come from interrupts/exception and from syscalls, merge. 584 584 */ 585 - restore_regs_and_iret: 585 + GLOBAL(restore_regs_and_iret) 586 586 RESTORE_EXTRA_REGS 587 587 restore_c_regs_and_iret: 588 588 RESTORE_C_REGS
+18 -38
arch/x86/entry/entry_64_compat.S
··· 202 202 ENTRY(entry_INT80_compat) 203 203 /* 204 204 * Interrupts are off on entry. 205 - * We do not frame this tiny irq-off block with TRACE_IRQS_OFF/ON, 206 - * it is too small to ever cause noticeable irq latency. 207 205 */ 208 206 PARAVIRT_ADJUST_EXCEPTION_FRAME 209 207 SWAPGS 210 - ENABLE_INTERRUPTS(CLBR_NONE) 211 208 212 - /* Zero-extending 32-bit regs, do not remove */ 209 + /* 210 + * User tracing code (ptrace or signal handlers) might assume that 211 + * the saved RAX contains a 32-bit number when we're invoking a 32-bit 212 + * syscall. Just in case the high bits are nonzero, zero-extend 213 + * the syscall number. (This could almost certainly be deleted 214 + * with no ill effects.) 215 + */ 213 216 movl %eax, %eax 214 217 215 218 /* Construct struct pt_regs on stack (iret frame is already on stack) */ ··· 235 232 pushq %r15 /* pt_regs->r15 */ 236 233 cld 237 234 238 - orl $TS_COMPAT, ASM_THREAD_INFO(TI_status, %rsp, SIZEOF_PTREGS) 239 - testl $_TIF_WORK_SYSCALL_ENTRY, ASM_THREAD_INFO(TI_flags, %rsp, SIZEOF_PTREGS) 240 - jnz ia32_tracesys 241 - 242 - ia32_do_call: 243 - /* 32-bit syscall -> 64-bit C ABI argument conversion */ 244 - movl %edi, %r8d /* arg5 */ 245 - movl %ebp, %r9d /* arg6 */ 246 - xchg %ecx, %esi /* rsi:arg2, rcx:arg4 */ 247 - movl %ebx, %edi /* arg1 */ 248 - movl %edx, %edx /* arg3 (zero extension) */ 249 - cmpq $(IA32_NR_syscalls-1), %rax 250 - ja 1f 251 - 252 - call *ia32_sys_call_table(, %rax, 8) 253 - movq %rax, RAX(%rsp) 254 - 1: 255 - RESTORE_EXTRA_REGS 256 - jmp int_ret_from_sys_call 257 - 258 - ia32_tracesys: 259 - movq %rsp, %rdi /* &pt_regs -> arg1 */ 260 - call syscall_trace_enter 261 235 /* 262 - * Reload arg registers from stack in case ptrace changed them. 263 - * Don't reload %eax because syscall_trace_enter() returned 264 - * the %rax value we should see. But do truncate it to 32 bits. 265 - * If it's -1 to make us punt the syscall, then (u32)-1 is still 266 - * an appropriately invalid value. 236 + * User mode is traced as though IRQs are on, and the interrupt 237 + * gate turned them off. 267 238 */ 268 - movl RCX(%rsp), %ecx 269 - movl RDX(%rsp), %edx 270 - movl RSI(%rsp), %esi 271 - movl RDI(%rsp), %edi 272 - movl %eax, %eax /* zero extension */ 273 - jmp ia32_do_call 239 + TRACE_IRQS_OFF 240 + 241 + movq %rsp, %rdi 242 + call do_int80_syscall_32 243 + 244 + /* Go back to user mode. */ 245 + TRACE_IRQS_ON 246 + SWAPGS 247 + jmp restore_regs_and_iret 274 248 END(entry_INT80_compat) 275 249 276 250 ALIGN