aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Schwidefsky <schwidefsky@de.ibm.com>2016-01-05 07:29:38 -0500
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2016-01-11 07:01:24 -0500
commit249c543b97e1409b13fb9539b2f880e58ddd87cf (patch)
tree956a0719238b56b8dffa3877d3fe3eb5c27df9f4
parent0dab3e0e59ac3692e2f95cb37ba17d5dfb3d1e5f (diff)
s390/vdso: optimize getcpu system call
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>
-rw-r--r--arch/s390/include/asm/vdso.h2
-rw-r--r--arch/s390/kernel/asm-offsets.c2
-rw-r--r--arch/s390/kernel/vdso.c9
-rw-r--r--arch/s390/kernel/vdso32/Makefile2
-rw-r--r--arch/s390/kernel/vdso32/getcpu.S43
-rw-r--r--arch/s390/kernel/vdso32/vdso32.lds.S1
-rw-r--r--arch/s390/kernel/vdso64/Makefile2
-rw-r--r--arch/s390/kernel/vdso64/getcpu.S42
-rw-r--r--arch/s390/kernel/vdso64/vdso64.lds.S1
9 files changed, 101 insertions, 3 deletions
diff --git a/arch/s390/include/asm/vdso.h b/arch/s390/include/asm/vdso.h
index f9b02d300d60..d0a2dbf2433d 100644
--- a/arch/s390/include/asm/vdso.h
+++ b/arch/s390/include/asm/vdso.h
@@ -38,6 +38,8 @@ struct vdso_data {
38struct vdso_per_cpu_data { 38struct vdso_per_cpu_data {
39 __u64 ectg_timer_base; 39 __u64 ectg_timer_base;
40 __u64 ectg_user_time; 40 __u64 ectg_user_time;
41 __u32 cpu_nr;
42 __u32 node_id;
41}; 43};
42 44
43extern struct vdso_data *vdso_data; 45extern struct vdso_data *vdso_data;
diff --git a/arch/s390/kernel/asm-offsets.c b/arch/s390/kernel/asm-offsets.c
index d5916ef9c619..53bbc9e8b281 100644
--- a/arch/s390/kernel/asm-offsets.c
+++ b/arch/s390/kernel/asm-offsets.c
@@ -80,6 +80,8 @@ int main(void)
80 OFFSET(__VDSO_TK_SHIFT, vdso_data, tk_shift); 80 OFFSET(__VDSO_TK_SHIFT, vdso_data, tk_shift);
81 OFFSET(__VDSO_ECTG_BASE, vdso_per_cpu_data, ectg_timer_base); 81 OFFSET(__VDSO_ECTG_BASE, vdso_per_cpu_data, ectg_timer_base);
82 OFFSET(__VDSO_ECTG_USER, vdso_per_cpu_data, ectg_user_time); 82 OFFSET(__VDSO_ECTG_USER, vdso_per_cpu_data, ectg_user_time);
83 OFFSET(__VDSO_CPU_NR, vdso_per_cpu_data, cpu_nr);
84 OFFSET(__VDSO_NODE_ID, vdso_per_cpu_data, node_id);
83 BLANK(); 85 BLANK();
84 /* constants used by the vdso */ 86 /* constants used by the vdso */
85 DEFINE(__CLOCK_REALTIME, CLOCK_REALTIME); 87 DEFINE(__CLOCK_REALTIME, CLOCK_REALTIME);
diff --git a/arch/s390/kernel/vdso.c b/arch/s390/kernel/vdso.c
index 604f4a68b524..94495cac8be3 100644
--- a/arch/s390/kernel/vdso.c
+++ b/arch/s390/kernel/vdso.c
@@ -80,7 +80,7 @@ struct vdso_data *vdso_data = &vdso_data_store.data;
80/* 80/*
81 * Setup vdso data page. 81 * Setup vdso data page.
82 */ 82 */
83static void vdso_init_data(struct vdso_data *vd) 83static void __init vdso_init_data(struct vdso_data *vd)
84{ 84{
85 vd->ectg_available = test_facility(31); 85 vd->ectg_available = test_facility(31);
86} 86}
@@ -93,6 +93,7 @@ static void vdso_init_data(struct vdso_data *vd)
93int vdso_alloc_per_cpu(struct lowcore *lowcore) 93int vdso_alloc_per_cpu(struct lowcore *lowcore)
94{ 94{
95 unsigned long segment_table, page_table, page_frame; 95 unsigned long segment_table, page_table, page_frame;
96 struct vdso_per_cpu_data *vd;
96 u32 *psal, *aste; 97 u32 *psal, *aste;
97 int i; 98 int i;
98 99
@@ -107,6 +108,12 @@ int vdso_alloc_per_cpu(struct lowcore *lowcore)
107 if (!segment_table || !page_table || !page_frame) 108 if (!segment_table || !page_table || !page_frame)
108 goto out; 109 goto out;
109 110
111 /* Initialize per-cpu vdso data page */
112 vd = (struct vdso_per_cpu_data *) page_frame;
113 vd->cpu_nr = lowcore->cpu_nr;
114 vd->node_id = cpu_to_node(vd->cpu_nr);
115
116 /* Set up access register mode page table */
110 clear_table((unsigned long *) segment_table, _SEGMENT_ENTRY_EMPTY, 117 clear_table((unsigned long *) segment_table, _SEGMENT_ENTRY_EMPTY,
111 PAGE_SIZE << SEGMENT_ORDER); 118 PAGE_SIZE << SEGMENT_ORDER);
112 clear_table((unsigned long *) page_table, _PAGE_INVALID, 119 clear_table((unsigned long *) page_table, _PAGE_INVALID,
diff --git a/arch/s390/kernel/vdso32/Makefile b/arch/s390/kernel/vdso32/Makefile
index ee8a18e50a25..f9c459586649 100644
--- a/arch/s390/kernel/vdso32/Makefile
+++ b/arch/s390/kernel/vdso32/Makefile
@@ -1,6 +1,6 @@
1# List of files in the vdso, has to be asm only for now 1# List of files in the vdso, has to be asm only for now
2 2
3obj-vdso32 = gettimeofday.o clock_getres.o clock_gettime.o note.o 3obj-vdso32 = gettimeofday.o clock_getres.o clock_gettime.o note.o getcpu.o
4 4
5# Build rules 5# Build rules
6 6
diff --git a/arch/s390/kernel/vdso32/getcpu.S b/arch/s390/kernel/vdso32/getcpu.S
new file mode 100644
index 000000000000..c1ed0b72030f
--- /dev/null
+++ b/arch/s390/kernel/vdso32/getcpu.S
@@ -0,0 +1,43 @@
1/*
2 * Userland implementation of getcpu() for 32 bits processes in a
3 * s390 kernel for use in the vDSO
4 *
5 * Copyright IBM Corp. 2016
6 * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
7 */
8#include <asm/vdso.h>
9#include <asm/asm-offsets.h>
10
11 .text
12 .align 4
13 .globl __kernel_getcpu
14 .type __kernel_getcpu,@function
15__kernel_getcpu:
16 .cfi_startproc
17 ear %r1,%a4
18 lhi %r4,1
19 sll %r4,24
20 sar %a4,%r4
21 la %r4,0
22 epsw %r0,0
23 sacf 512
24 l %r5,__VDSO_CPU_NR(%r4)
25 l %r4,__VDSO_NODE_ID(%r4)
26 tml %r0,0x4000
27 jo 1f
28 tml %r0,0x8000
29 jno 0f
30 sacf 256
31 j 1f
320: sacf 0
331: sar %a4,%r1
34 ltr %r2,%r2
35 jz 2f
36 st %r5,0(%r2)
372: ltr %r3,%r3
38 jz 3f
39 st %r4,0(%r3)
403: lhi %r2,0
41 br %r14
42 .cfi_endproc
43 .size __kernel_getcpu,.-__kernel_getcpu
diff --git a/arch/s390/kernel/vdso32/vdso32.lds.S b/arch/s390/kernel/vdso32/vdso32.lds.S
index a8c379fa1247..8f048c2d6d13 100644
--- a/arch/s390/kernel/vdso32/vdso32.lds.S
+++ b/arch/s390/kernel/vdso32/vdso32.lds.S
@@ -132,6 +132,7 @@ VERSION
132 __kernel_gettimeofday; 132 __kernel_gettimeofday;
133 __kernel_clock_gettime; 133 __kernel_clock_gettime;
134 __kernel_clock_getres; 134 __kernel_clock_getres;
135 __kernel_getcpu;
135 136
136 local: *; 137 local: *;
137 }; 138 };
diff --git a/arch/s390/kernel/vdso64/Makefile b/arch/s390/kernel/vdso64/Makefile
index c4b03f9ed228..058659c1b8cf 100644
--- a/arch/s390/kernel/vdso64/Makefile
+++ b/arch/s390/kernel/vdso64/Makefile
@@ -1,6 +1,6 @@
1# List of files in the vdso, has to be asm only for now 1# List of files in the vdso, has to be asm only for now
2 2
3obj-vdso64 = gettimeofday.o clock_getres.o clock_gettime.o note.o 3obj-vdso64 = gettimeofday.o clock_getres.o clock_gettime.o note.o getcpu.o
4 4
5# Build rules 5# Build rules
6 6
diff --git a/arch/s390/kernel/vdso64/getcpu.S b/arch/s390/kernel/vdso64/getcpu.S
new file mode 100644
index 000000000000..4cbe98291931
--- /dev/null
+++ b/arch/s390/kernel/vdso64/getcpu.S
@@ -0,0 +1,42 @@
1/*
2 * Userland implementation of getcpu() for 64 bits processes in a
3 * s390 kernel for use in the vDSO
4 *
5 * Copyright IBM Corp. 2016
6 * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
7 */
8#include <asm/vdso.h>
9#include <asm/asm-offsets.h>
10
11 .text
12 .align 4
13 .globl __kernel_getcpu
14 .type __kernel_getcpu,@function
15__kernel_getcpu:
16 .cfi_startproc
17 ear %r1,%a4
18 llilh %r4,0x0100
19 sar %a4,%r4
20 la %r4,0
21 epsw %r0,0
22 sacf 512
23 l %r5,__VDSO_CPU_NR(%r4)
24 l %r4,__VDSO_NODE_ID(%r4)
25 tml %r0,0x4000
26 jo 1f
27 tml %r0,0x8000
28 jno 0f
29 sacf 256
30 j 1f
310: sacf 0
321: sar %a4,%r1
33 ltgr %r2,%r2
34 jz 2f
35 st %r5,0(%r2)
362: ltgr %r3,%r3
37 jz 3f
38 st %r4,0(%r3)
393: lghi %r2,0
40 br %r14
41 .cfi_endproc
42 .size __kernel_getcpu,.-__kernel_getcpu
diff --git a/arch/s390/kernel/vdso64/vdso64.lds.S b/arch/s390/kernel/vdso64/vdso64.lds.S
index 9f5979d102a9..f35455d497fe 100644
--- a/arch/s390/kernel/vdso64/vdso64.lds.S
+++ b/arch/s390/kernel/vdso64/vdso64.lds.S
@@ -132,6 +132,7 @@ VERSION
132 __kernel_gettimeofday; 132 __kernel_gettimeofday;
133 __kernel_clock_gettime; 133 __kernel_clock_gettime;
134 __kernel_clock_getres; 134 __kernel_clock_getres;
135 __kernel_getcpu;
135 136
136 local: *; 137 local: *;
137 }; 138 };