/* * i386 linux replacement vdso. * * Copyright 2023 Linaro, Ltd. * * SPDX-License-Identifier: GPL-2.0-or-later */ #include #include "vdso-asmoffset.h" .macro endf name .globl \name .type \name, @function .size \name, . - \name .endm .macro vdso_syscall1 name, nr \name: .cfi_startproc mov %ebx, %edx .cfi_register %ebx, %edx mov 4(%esp), %ebx mov $\nr, %eax int $0x80 mov %edx, %ebx ret .cfi_endproc endf \name .endm .macro vdso_syscall2 name, nr \name: .cfi_startproc mov %ebx, %edx .cfi_register %ebx, %edx mov 4(%esp), %ebx mov 8(%esp), %ecx mov $\nr, %eax int $0x80 mov %edx, %ebx ret .cfi_endproc endf \name .endm .macro vdso_syscall3 name, nr \name: .cfi_startproc push %ebx .cfi_adjust_cfa_offset 4 .cfi_rel_offset %ebx, 0 mov 8(%esp), %ebx mov 12(%esp), %ecx mov 16(%esp), %edx mov $\nr, %eax int $0x80 pop %ebx .cfi_adjust_cfa_offset -4 .cfi_restore %ebx ret .cfi_endproc endf \name .endm __kernel_vsyscall: .cfi_startproc int $0x80 ret .cfi_endproc endf __kernel_vsyscall vdso_syscall2 __vdso_clock_gettime, __NR_clock_gettime vdso_syscall2 __vdso_clock_gettime64, __NR_clock_gettime64 vdso_syscall2 __vdso_clock_getres, __NR_clock_getres vdso_syscall2 __vdso_gettimeofday, __NR_gettimeofday vdso_syscall1 __vdso_time, __NR_time vdso_syscall3 __vdso_getcpu, __NR_gettimeofday /* * Signal return handlers. */ .cfi_startproc simple .cfi_signal_frame /* * For convenience, put the cfa just above eip in sigcontext, and count * offsets backward from there. Re-compute the cfa in the two contexts * we have for signal unwinding. This is far simpler than the * DW_CFA_expression form that the kernel uses, and is equally correct. */ .cfi_def_cfa %esp, SIGFRAME_SIGCONTEXT_eip + 4 .cfi_offset %eip, -4 /* err, -8 */ /* trapno, -12 */ .cfi_offset %eax, -16 .cfi_offset %ecx, -20 .cfi_offset %edx, -24 .cfi_offset %ebx, -28 .cfi_offset %esp, -32 .cfi_offset %ebp, -36 .cfi_offset %esi, -40 .cfi_offset %edi, -44 /* * While this frame is marked as a signal frame, that only applies to how * the return address is handled for the outer frame. The return address * that arrived here, from the inner frame, is not marked as a signal frame * and so the unwinder still tries to subtract 1 to examine the presumed * call insn. Thus we must extend the unwind info to a nop before the start. */ nop __kernel_sigreturn: popl %eax /* pop sig */ .cfi_adjust_cfa_offset -4 movl $__NR_sigreturn, %eax int $0x80 endf __kernel_sigreturn .cfi_def_cfa_offset RT_SIGFRAME_SIGCONTEXT_eip + 4 nop __kernel_rt_sigreturn: movl $__NR_rt_sigreturn, %eax int $0x80 endf __kernel_rt_sigreturn .cfi_endproc /* * TODO: Add elf notes. E.g. * * #include * ELFNOTE_START(Linux, 0, "a") * .long LINUX_VERSION_CODE * ELFNOTE_END * * but what version number would we set for QEMU? */