aboutsummaryrefslogtreecommitdiff
path: root/linux-user/x86_64/vdso.S
diff options
context:
space:
mode:
authorRichard Henderson <richard.henderson@linaro.org>2021-06-17 14:39:14 -0700
committerRichard Henderson <richard.henderson@linaro.org>2023-10-30 13:41:55 -0700
commit6b1a9d38b570d6b2812711cfadb6eb60ed3a709d (patch)
tree49ffd6a20950060cb6371cfff337de35917a52a8 /linux-user/x86_64/vdso.S
parenta1367443bac790c8385aca008f4b3bf9eaa8c137 (diff)
linux-user/x86_64: Add vdso
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Diffstat (limited to 'linux-user/x86_64/vdso.S')
-rw-r--r--linux-user/x86_64/vdso.S78
1 files changed, 78 insertions, 0 deletions
diff --git a/linux-user/x86_64/vdso.S b/linux-user/x86_64/vdso.S
new file mode 100644
index 0000000000..47d16c00ab
--- /dev/null
+++ b/linux-user/x86_64/vdso.S
@@ -0,0 +1,78 @@
+/*
+ * 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 */