blob: 47d16c00ab1ed539e8cb73c969d684782d2669b4 [file] [log] [blame]
/*
* x86-64 linux replacement vdso.
*
* Copyright 2023 Linaro, Ltd.
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include <asm/unistd.h>
.macro endf name
.globl \name
.type \name, @function
.size \name, . - \name
.endm
.macro weakalias name
\name = __vdso_\name
.weak \name
.endm
.macro vdso_syscall name, nr
__vdso_\name:
mov $\nr, %eax
syscall
ret
endf __vdso_\name
weakalias \name
.endm
.cfi_startproc
vdso_syscall clock_gettime, __NR_clock_gettime
vdso_syscall clock_getres, __NR_clock_getres
vdso_syscall gettimeofday, __NR_gettimeofday
vdso_syscall time, __NR_time
__vdso_getcpu:
/*
* There is no syscall number for this allocated on x64.
* We can handle this several ways:
*
* (1) Invent a syscall number for use within qemu.
* It should be easy enough to pick a number that
* is well out of the way of the kernel numbers.
*
* (2) Force the emulated cpu to support the rdtscp insn,
* and initialize the TSC_AUX value the appropriate value.
*
* (3) Pretend that we're always running on cpu 0.
*
* This last is the one that's implemented here, with the
* tiny bit of extra code to support rdtscp in place.
*/
xor %ecx, %ecx /* rdtscp w/ tsc_aux = 0 */
/* if (cpu != NULL) *cpu = (ecx & 0xfff); */
test %rdi, %rdi
jz 1f
mov %ecx, %eax
and $0xfff, %eax
mov %eax, (%rdi)
/* if (node != NULL) *node = (ecx >> 12); */
1: test %rsi, %rsi
jz 2f
shr $12, %ecx
mov %ecx, (%rsi)
2: xor %eax, %eax
ret
endf __vdso_getcpu
weakalias getcpu
.cfi_endproc
/* TODO: Add elf note for LINUX_VERSION_CODE */