Skip to content

Commit

Permalink
s390/vdso: optimize getcpu system call
Browse files Browse the repository at this point in the history
Add the CPU number to the per-cpu vdso data page and add the
__kernel_getcpu function to the vdso object to retrieve the
CPU number in user space.

Suggested-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Reviewed-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
  • Loading branch information
Martin Schwidefsky committed Jan 11, 2016
1 parent 0dab3e0 commit 249c543
Show file tree
Hide file tree
Showing 9 changed files with 101 additions and 3 deletions.
2 changes: 2 additions & 0 deletions arch/s390/include/asm/vdso.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ struct vdso_data {
struct vdso_per_cpu_data {
__u64 ectg_timer_base;
__u64 ectg_user_time;
__u32 cpu_nr;
__u32 node_id;
};

extern struct vdso_data *vdso_data;
Expand Down
2 changes: 2 additions & 0 deletions arch/s390/kernel/asm-offsets.c
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@ int main(void)
OFFSET(__VDSO_TK_SHIFT, vdso_data, tk_shift);
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);
BLANK();
/* constants used by the vdso */
DEFINE(__CLOCK_REALTIME, CLOCK_REALTIME);
Expand Down
9 changes: 8 additions & 1 deletion arch/s390/kernel/vdso.c
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ struct vdso_data *vdso_data = &vdso_data_store.data;
/*
* Setup vdso data page.
*/
static void vdso_init_data(struct vdso_data *vd)
static void __init vdso_init_data(struct vdso_data *vd)
{
vd->ectg_available = test_facility(31);
}
Expand All @@ -93,6 +93,7 @@ static void vdso_init_data(struct vdso_data *vd)
int vdso_alloc_per_cpu(struct lowcore *lowcore)
{
unsigned long segment_table, page_table, page_frame;
struct vdso_per_cpu_data *vd;
u32 *psal, *aste;
int i;

Expand All @@ -107,6 +108,12 @@ int vdso_alloc_per_cpu(struct lowcore *lowcore)
if (!segment_table || !page_table || !page_frame)
goto out;

/* Initialize per-cpu vdso data page */
vd = (struct vdso_per_cpu_data *) page_frame;
vd->cpu_nr = lowcore->cpu_nr;
vd->node_id = cpu_to_node(vd->cpu_nr);

/* Set up access register mode page table */
clear_table((unsigned long *) segment_table, _SEGMENT_ENTRY_EMPTY,
PAGE_SIZE << SEGMENT_ORDER);
clear_table((unsigned long *) page_table, _PAGE_INVALID,
Expand Down
2 changes: 1 addition & 1 deletion arch/s390/kernel/vdso32/Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# List of files in the vdso, has to be asm only for now

obj-vdso32 = gettimeofday.o clock_getres.o clock_gettime.o note.o
obj-vdso32 = gettimeofday.o clock_getres.o clock_gettime.o note.o getcpu.o

# Build rules

Expand Down
43 changes: 43 additions & 0 deletions arch/s390/kernel/vdso32/getcpu.S
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* Userland implementation of getcpu() for 32 bits processes in a
* s390 kernel for use in the vDSO
*
* Copyright IBM Corp. 2016
* Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
*/
#include <asm/vdso.h>
#include <asm/asm-offsets.h>

.text
.align 4
.globl __kernel_getcpu
.type __kernel_getcpu,@function
__kernel_getcpu:
.cfi_startproc
ear %r1,%a4
lhi %r4,1
sll %r4,24
sar %a4,%r4
la %r4,0
epsw %r0,0
sacf 512
l %r5,__VDSO_CPU_NR(%r4)
l %r4,__VDSO_NODE_ID(%r4)
tml %r0,0x4000
jo 1f
tml %r0,0x8000
jno 0f
sacf 256
j 1f
0: sacf 0
1: sar %a4,%r1
ltr %r2,%r2
jz 2f
st %r5,0(%r2)
2: ltr %r3,%r3
jz 3f
st %r4,0(%r3)
3: lhi %r2,0
br %r14
.cfi_endproc
.size __kernel_getcpu,.-__kernel_getcpu
1 change: 1 addition & 0 deletions arch/s390/kernel/vdso32/vdso32.lds.S
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ VERSION
__kernel_gettimeofday;
__kernel_clock_gettime;
__kernel_clock_getres;
__kernel_getcpu;

local: *;
};
Expand Down
2 changes: 1 addition & 1 deletion arch/s390/kernel/vdso64/Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# List of files in the vdso, has to be asm only for now

obj-vdso64 = gettimeofday.o clock_getres.o clock_gettime.o note.o
obj-vdso64 = gettimeofday.o clock_getres.o clock_gettime.o note.o getcpu.o

# Build rules

Expand Down
42 changes: 42 additions & 0 deletions arch/s390/kernel/vdso64/getcpu.S
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* Userland implementation of getcpu() for 64 bits processes in a
* s390 kernel for use in the vDSO
*
* Copyright IBM Corp. 2016
* Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
*/
#include <asm/vdso.h>
#include <asm/asm-offsets.h>

.text
.align 4
.globl __kernel_getcpu
.type __kernel_getcpu,@function
__kernel_getcpu:
.cfi_startproc
ear %r1,%a4
llilh %r4,0x0100
sar %a4,%r4
la %r4,0
epsw %r0,0
sacf 512
l %r5,__VDSO_CPU_NR(%r4)
l %r4,__VDSO_NODE_ID(%r4)
tml %r0,0x4000
jo 1f
tml %r0,0x8000
jno 0f
sacf 256
j 1f
0: sacf 0
1: sar %a4,%r1
ltgr %r2,%r2
jz 2f
st %r5,0(%r2)
2: ltgr %r3,%r3
jz 3f
st %r4,0(%r3)
3: lghi %r2,0
br %r14
.cfi_endproc
.size __kernel_getcpu,.-__kernel_getcpu
1 change: 1 addition & 0 deletions arch/s390/kernel/vdso64/vdso64.lds.S
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ VERSION
__kernel_gettimeofday;
__kernel_clock_gettime;
__kernel_clock_getres;
__kernel_getcpu;

local: *;
};
Expand Down

0 comments on commit 249c543

Please sign in to comment.