s390/vdso: fix getcpu
authorHeiko Carstens <heiko.carstens@de.ibm.com>
Mon, 18 Nov 2019 08:38:37 +0000 (09:38 +0100)
committerVasily Gorbik <gor@linux.ibm.com>
Sat, 30 Nov 2019 09:52:44 +0000 (10:52 +0100)
getcpu reads the required values for cpu and node with two
instructions. This might lead to an inconsistent result if user space
gets preempted and migrated to a different CPU between the two
instructions.

Fix this by using just a single instruction to read both values at
once.

This is currently rather a theoretical bug, since there is no real
NUMA support available (except for NUMA emulation).

Reviewed-by: Christian Borntraeger <borntraeger@de.ibm.com>
Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
arch/s390/include/asm/vdso.h
arch/s390/kernel/asm-offsets.c
arch/s390/kernel/vdso32/getcpu.S
arch/s390/kernel/vdso64/getcpu.S

index 169d760..3bcfdeb 100644 (file)
@@ -41,8 +41,17 @@ struct vdso_data {
 struct vdso_per_cpu_data {
        __u64 ectg_timer_base;
        __u64 ectg_user_time;
-       __u32 cpu_nr;
-       __u32 node_id;
+       /*
+        * Note: node_id and cpu_nr must be at adjacent memory locations.
+        * VDSO userspace must read both values with a single instruction.
+        */
+       union {
+               __u64 getcpu_val;
+               struct {
+                       __u32 node_id;
+                       __u32 cpu_nr;
+               };
+       };
 };
 
 extern struct vdso_data *vdso_data;
index 41ac4ad..ce33406 100644 (file)
@@ -78,8 +78,7 @@ int main(void)
        OFFSET(__VDSO_TS_END, vdso_data, ts_end);
        OFFSET(__VDSO_ECTG_BASE, vdso_per_cpu_data, ectg_timer_base);
        OFFSET(__VDSO_ECTG_USER, vdso_per_cpu_data, ectg_user_time);
-       OFFSET(__VDSO_CPU_NR, vdso_per_cpu_data, cpu_nr);
-       OFFSET(__VDSO_NODE_ID, vdso_per_cpu_data, node_id);
+       OFFSET(__VDSO_GETCPU_VAL, vdso_per_cpu_data, getcpu_val);
        BLANK();
        /* constants used by the vdso */
        DEFINE(__CLOCK_REALTIME, CLOCK_REALTIME);
index 25515f3..dc79e16 100644 (file)
        .type  __kernel_getcpu,@function
 __kernel_getcpu:
        CFI_STARTPROC
-       la      %r4,0
        sacf    256
-       l       %r5,__VDSO_CPU_NR(%r4)
-       l       %r4,__VDSO_NODE_ID(%r4)
+       lm      %r4,%r5,__VDSO_GETCPU_VAL(%r0)
        sacf    0
        ltr     %r2,%r2
        jz      2f
index 2446e9d..3c04f73 100644 (file)
        .type  __kernel_getcpu,@function
 __kernel_getcpu:
        CFI_STARTPROC
-       la      %r4,0
        sacf    256
-       l       %r5,__VDSO_CPU_NR(%r4)
-       l       %r4,__VDSO_NODE_ID(%r4)
+       lm      %r4,%r5,__VDSO_GETCPU_VAL(%r0)
        sacf    0
        ltgr    %r2,%r2
        jz      2f