s390/vdso: reimplement getcpu vdso syscall
authorHeiko Carstens <hca@linux.ibm.com>
Mon, 16 Nov 2020 07:06:41 +0000 (08:06 +0100)
committerHeiko Carstens <hca@linux.ibm.com>
Mon, 23 Nov 2020 11:01:13 +0000 (12:01 +0100)
Implement the previously removed getcpu vdso syscall by using the
TOD programmable field to pass the cpu number to user space.

Reviewed-by: Sven Schnelle <svens@linux.ibm.com>
Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
arch/s390/include/asm/timex.h
arch/s390/include/asm/vdso.h
arch/s390/kernel/smp.c
arch/s390/kernel/vdso.c
arch/s390/kernel/vdso64/Makefile
arch/s390/kernel/vdso64/getcpu.c [new file with mode: 0644]
arch/s390/kernel/vdso64/vdso64.lds.S
arch/s390/kernel/vdso64/vdso_user_wrapper.S

index 289aaff..c8e244e 100644 (file)
@@ -49,6 +49,13 @@ static inline void set_clock_comparator(__u64 time)
        asm volatile("sckc %0" : : "Q" (time));
 }
 
+static inline void set_tod_programmable_field(u16 val)
+{
+       register unsigned long reg0 asm("0") = val;
+
+       asm volatile("sckpf" : : "d" (reg0));
+}
+
 void clock_comparator_work(void);
 
 void __init time_early_init(void);
index 9b299c0..f655908 100644 (file)
@@ -14,5 +14,7 @@
 
 extern struct vdso_data *vdso_data;
 
+void vdso_getcpu_init(void);
+
 #endif /* __ASSEMBLY__ */
 #endif /* __S390_VDSO_H__ */
index 7f7d81f..647226e 100644 (file)
@@ -54,6 +54,7 @@
 #include <asm/nmi.h>
 #include <asm/stacktrace.h>
 #include <asm/topology.h>
+#include <asm/vdso.h>
 #include "entry.h"
 
 enum {
@@ -858,6 +859,7 @@ static void smp_init_secondary(void)
        preempt_disable();
        init_cpu_timer();
        vtime_init();
+       vdso_getcpu_init();
        pfault_init();
        notify_cpu_starting(cpu);
        if (topology_cpu_dedicated(cpu))
index 53c983f..aef2edf 100644 (file)
@@ -29,6 +29,7 @@
 #include <asm/sections.h>
 #include <asm/vdso.h>
 #include <asm/facility.h>
+#include <asm/timex.h>
 
 extern char vdso64_start, vdso64_end;
 static void *vdso64_kbase = &vdso64_start;
@@ -100,6 +101,11 @@ static union {
 } vdso_data_store __page_aligned_data;
 struct vdso_data *vdso_data = (struct vdso_data *)&vdso_data_store.data;
 
+void vdso_getcpu_init(void)
+{
+       set_tod_programmable_field(smp_processor_id());
+}
+
 /*
  * This is called from binfmt_elf, we create the special vma for the
  * vDSO and insert it into the mm struct tree
@@ -170,6 +176,7 @@ static int __init vdso_init(void)
 {
        int i;
 
+       vdso_getcpu_init();
        /* Calculate the size of the 64 bit vDSO */
        vdso64_pages = ((&vdso64_end - &vdso64_start
                         + PAGE_SIZE - 1) >> PAGE_SHIFT) + 1;
index b0cf58a..a6e0fb6 100644 (file)
@@ -7,7 +7,8 @@ ARCH_REL_TYPE_ABS += R_390_GOT|R_390_PLT
 
 include $(srctree)/lib/vdso/Makefile
 obj-vdso64 = vdso_user_wrapper.o note.o
-obj-cvdso64 = vdso64_generic.o
+obj-cvdso64 = vdso64_generic.o getcpu.o
+CFLAGS_REMOVE_getcpu.o = -pg $(CC_FLAGS_FTRACE) $(CC_FLAGS_EXPOLINE)
 CFLAGS_REMOVE_vdso64_generic.o = -pg $(CC_FLAGS_FTRACE) $(CC_FLAGS_EXPOLINE)
 
 # Build rules
diff --git a/arch/s390/kernel/vdso64/getcpu.c b/arch/s390/kernel/vdso64/getcpu.c
new file mode 100644 (file)
index 0000000..a5da7a9
--- /dev/null
@@ -0,0 +1,20 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright IBM Corp. 2020 */
+
+#include <linux/compiler.h>
+#include <linux/getcpu.h>
+#include <asm/timex.h>
+
+int __s390_vdso_getcpu(unsigned *cpu, unsigned *node, struct getcpu_cache *unused)
+{
+       __u16 todval[8];
+
+       /* CPU number is stored in the programmable field of the TOD clock */
+       get_tod_clock_ext((char *)todval);
+       if (cpu)
+               *cpu = todval[7];
+       /* NUMA node is always zero */
+       if (node)
+               *node = 0;
+       return 0;
+}
index b590065..7bde390 100644 (file)
@@ -135,7 +135,7 @@ VERSION
                __kernel_gettimeofday;
                __kernel_clock_gettime;
                __kernel_clock_getres;
-
+               __kernel_getcpu;
        local: *;
        };
 }
index a775d7e..f773505 100644 (file)
@@ -36,3 +36,4 @@ __kernel_\func:
 vdso_func gettimeofday
 vdso_func clock_getres
 vdso_func clock_gettime
+vdso_func getcpu