xref: /qemu/linux-user/x86_64/vdso.S (revision 73b49878)
1/*
2 * x86-64 linux replacement vdso.
3 *
4 * Copyright 2023 Linaro, Ltd.
5 *
6 * SPDX-License-Identifier: GPL-2.0-or-later
7 */
8
9#include <asm/unistd.h>
10
11.macro endf name
12	.globl	\name
13	.type	\name, @function
14	.size	\name, . - \name
15.endm
16
17.macro weakalias name
18\name	= __vdso_\name
19	.weak	\name
20.endm
21
22.macro vdso_syscall name, nr
23__vdso_\name:
24	mov	$\nr, %eax
25	syscall
26	ret
27endf	__vdso_\name
28weakalias \name
29.endm
30
31	.cfi_startproc
32
33vdso_syscall clock_gettime, __NR_clock_gettime
34vdso_syscall clock_getres, __NR_clock_getres
35vdso_syscall gettimeofday, __NR_gettimeofday
36vdso_syscall time, __NR_time
37
38__vdso_getcpu:
39	/*
40         * There is no syscall number for this allocated on x64.
41	 * We can handle this several ways:
42         *
43	 * (1) Invent a syscall number for use within qemu.
44         *     It should be easy enough to pick a number that
45         *     is well out of the way of the kernel numbers.
46         *
47         * (2) Force the emulated cpu to support the rdtscp insn,
48	 *     and initialize the TSC_AUX value the appropriate value.
49         *
50	 * (3) Pretend that we're always running on cpu 0.
51         *
52	 * This last is the one that's implemented here, with the
53	 * tiny bit of extra code to support rdtscp in place.
54         */
55	xor	%ecx, %ecx		/* rdtscp w/ tsc_aux = 0 */
56
57	/* if (cpu != NULL) *cpu = (ecx & 0xfff); */
58	test	%rdi, %rdi
59	jz	1f
60	mov	%ecx, %eax
61	and	$0xfff, %eax
62	mov	%eax, (%rdi)
63
64	/* if (node != NULL) *node = (ecx >> 12); */
651:	test	%rsi, %rsi
66	jz	2f
67	shr	$12, %ecx
68	mov	%ecx, (%rsi)
69
702:	xor	%eax, %eax
71	ret
72endf	__vdso_getcpu
73
74weakalias getcpu
75
76	.cfi_endproc
77
78/* TODO: Add elf note for LINUX_VERSION_CODE */
79