s390/vdso: fix getcpu

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>
This commit is contained in:
Heiko Carstens 2019-11-18 09:38:37 +01:00 committed by Vasily Gorbik
parent a2308c11ec
commit 5a5525b048
4 changed files with 14 additions and 10 deletions

View File

@ -41,8 +41,17 @@ struct vdso_data {
struct vdso_per_cpu_data { struct vdso_per_cpu_data {
__u64 ectg_timer_base; __u64 ectg_timer_base;
__u64 ectg_user_time; __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; extern struct vdso_data *vdso_data;

View File

@ -78,8 +78,7 @@ int main(void)
OFFSET(__VDSO_TS_END, vdso_data, ts_end); OFFSET(__VDSO_TS_END, vdso_data, ts_end);
OFFSET(__VDSO_ECTG_BASE, vdso_per_cpu_data, ectg_timer_base); OFFSET(__VDSO_ECTG_BASE, vdso_per_cpu_data, ectg_timer_base);
OFFSET(__VDSO_ECTG_USER, vdso_per_cpu_data, ectg_user_time); OFFSET(__VDSO_ECTG_USER, vdso_per_cpu_data, ectg_user_time);
OFFSET(__VDSO_CPU_NR, vdso_per_cpu_data, cpu_nr); OFFSET(__VDSO_GETCPU_VAL, vdso_per_cpu_data, getcpu_val);
OFFSET(__VDSO_NODE_ID, vdso_per_cpu_data, node_id);
BLANK(); BLANK();
/* constants used by the vdso */ /* constants used by the vdso */
DEFINE(__CLOCK_REALTIME, CLOCK_REALTIME); DEFINE(__CLOCK_REALTIME, CLOCK_REALTIME);

View File

@ -16,10 +16,8 @@
.type __kernel_getcpu,@function .type __kernel_getcpu,@function
__kernel_getcpu: __kernel_getcpu:
CFI_STARTPROC CFI_STARTPROC
la %r4,0
sacf 256 sacf 256
l %r5,__VDSO_CPU_NR(%r4) lm %r4,%r5,__VDSO_GETCPU_VAL(%r0)
l %r4,__VDSO_NODE_ID(%r4)
sacf 0 sacf 0
ltr %r2,%r2 ltr %r2,%r2
jz 2f jz 2f

View File

@ -16,10 +16,8 @@
.type __kernel_getcpu,@function .type __kernel_getcpu,@function
__kernel_getcpu: __kernel_getcpu:
CFI_STARTPROC CFI_STARTPROC
la %r4,0
sacf 256 sacf 256
l %r5,__VDSO_CPU_NR(%r4) lm %r4,%r5,__VDSO_GETCPU_VAL(%r0)
l %r4,__VDSO_NODE_ID(%r4)
sacf 0 sacf 0
ltgr %r2,%r2 ltgr %r2,%r2
jz 2f jz 2f