summaryrefslogtreecommitdiff
path: root/arch/loongarch/vdso
diff options
context:
space:
mode:
authorHuacai Chen <chenhuacai@loongson.cn>2022-08-06 15:19:33 +0800
committerHuacai Chen <chenhuacai@loongson.cn>2022-08-12 13:10:11 +0800
commitdce6098b22d58e5b646b1c67174c53f5a6a05605 (patch)
tree0658f8ef3b5efcf58a386100c02b1930bbd9eea0 /arch/loongarch/vdso
parent57fc7323a8e7c2e7c1d5795ab63cb3ffea3cfdfb (diff)
LoongArch: Add vDSO syscall __vdso_getcpu()
We test 20 million times of getcpu(), the real syscall version take 25 seconds, while the vsyscall version take only 2.4 seconds. Signed-off-by: Rui Wang <wangrui@loongson.cn> Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
Diffstat (limited to 'arch/loongarch/vdso')
-rw-r--r--arch/loongarch/vdso/Makefile2
-rw-r--r--arch/loongarch/vdso/vdso.lds.S1
-rw-r--r--arch/loongarch/vdso/vgetcpu.c43
3 files changed, 45 insertions, 1 deletions
diff --git a/arch/loongarch/vdso/Makefile b/arch/loongarch/vdso/Makefile
index 92e404032257..d89e2ac75f7b 100644
--- a/arch/loongarch/vdso/Makefile
+++ b/arch/loongarch/vdso/Makefile
@@ -6,7 +6,7 @@
ARCH_REL_TYPE_ABS := R_LARCH_32|R_LARCH_64|R_LARCH_MARK_LA|R_LARCH_JUMP_SLOT
include $(srctree)/lib/vdso/Makefile
-obj-vdso-y := elf.o vgettimeofday.o sigreturn.o
+obj-vdso-y := elf.o vgetcpu.o vgettimeofday.o sigreturn.o
# Common compiler flags between ABIs.
ccflags-vdso := \
diff --git a/arch/loongarch/vdso/vdso.lds.S b/arch/loongarch/vdso/vdso.lds.S
index 955f02de4a2d..56ad855896de 100644
--- a/arch/loongarch/vdso/vdso.lds.S
+++ b/arch/loongarch/vdso/vdso.lds.S
@@ -58,6 +58,7 @@ VERSION
{
LINUX_5.10 {
global:
+ __vdso_getcpu;
__vdso_clock_getres;
__vdso_clock_gettime;
__vdso_gettimeofday;
diff --git a/arch/loongarch/vdso/vgetcpu.c b/arch/loongarch/vdso/vgetcpu.c
new file mode 100644
index 000000000000..43a0078e4418
--- /dev/null
+++ b/arch/loongarch/vdso/vgetcpu.c
@@ -0,0 +1,43 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Fast user context implementation of getcpu()
+ */
+
+#include <asm/vdso.h>
+#include <linux/getcpu.h>
+
+static __always_inline int read_cpu_id(void)
+{
+ int cpu_id;
+
+ __asm__ __volatile__(
+ " rdtime.d $zero, %0\n"
+ : "=r" (cpu_id)
+ :
+ : "memory");
+
+ return cpu_id;
+}
+
+static __always_inline const struct vdso_pcpu_data *get_pcpu_data(void)
+{
+ return (struct vdso_pcpu_data *)(get_vdso_base() - VDSO_DATA_SIZE);
+}
+
+int __vdso_getcpu(unsigned int *cpu, unsigned int *node, struct getcpu_cache *unused)
+{
+ int cpu_id;
+ const struct vdso_pcpu_data *data;
+
+ cpu_id = read_cpu_id();
+
+ if (cpu)
+ *cpu = cpu_id;
+
+ if (node) {
+ data = get_pcpu_data();
+ *node = data[cpu_id].node;
+ }
+
+ return 0;
+}