144 lines
2.8 KiB
ArmAsm
144 lines
2.8 KiB
ArmAsm
|
/*
|
||
|
* i386 linux replacement vdso.
|
||
|
*
|
||
|
* Copyright 2023 Linaro, Ltd.
|
||
|
*
|
||
|
* SPDX-License-Identifier: GPL-2.0-or-later
|
||
|
*/
|
||
|
|
||
|
#include <asm/unistd.h>
|
||
|
#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 <linux/elfnote.h>
|
||
|
* ELFNOTE_START(Linux, 0, "a")
|
||
|
* .long LINUX_VERSION_CODE
|
||
|
* ELFNOTE_END
|
||
|
*
|
||
|
* but what version number would we set for QEMU?
|
||
|
*/
|