aboutsummaryrefslogtreecommitdiff
path: root/arch/loongarch/vdso/vgetcpu.c
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/vgetcpu.c
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/vgetcpu.c')
-rw-r--r--arch/loongarch/vdso/vgetcpu.c43
1 files changed, 43 insertions, 0 deletions
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;
+}