diff options
author | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2016-01-05 07:29:38 -0500 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2016-01-11 07:01:24 -0500 |
commit | 249c543b97e1409b13fb9539b2f880e58ddd87cf (patch) | |
tree | 956a0719238b56b8dffa3877d3fe3eb5c27df9f4 | |
parent | 0dab3e0e59ac3692e2f95cb37ba17d5dfb3d1e5f (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.h | 2 | ||||
-rw-r--r-- | arch/s390/kernel/asm-offsets.c | 2 | ||||
-rw-r--r-- | arch/s390/kernel/vdso.c | 9 | ||||
-rw-r--r-- | arch/s390/kernel/vdso32/Makefile | 2 | ||||
-rw-r--r-- | arch/s390/kernel/vdso32/getcpu.S | 43 | ||||
-rw-r--r-- | arch/s390/kernel/vdso32/vdso32.lds.S | 1 | ||||
-rw-r--r-- | arch/s390/kernel/vdso64/Makefile | 2 | ||||
-rw-r--r-- | arch/s390/kernel/vdso64/getcpu.S | 42 | ||||
-rw-r--r-- | arch/s390/kernel/vdso64/vdso64.lds.S | 1 |
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 { | |||
38 | struct vdso_per_cpu_data { | 38 | struct 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 | ||
43 | extern struct vdso_data *vdso_data; | 45 | extern 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 | */ |
83 | static void vdso_init_data(struct vdso_data *vd) | 83 | static 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) | |||
93 | int vdso_alloc_per_cpu(struct lowcore *lowcore) | 93 | int 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 | ||
3 | obj-vdso32 = gettimeofday.o clock_getres.o clock_gettime.o note.o | 3 | obj-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 | ||
32 | 0: sacf 0 | ||
33 | 1: sar %a4,%r1 | ||
34 | ltr %r2,%r2 | ||
35 | jz 2f | ||
36 | st %r5,0(%r2) | ||
37 | 2: ltr %r3,%r3 | ||
38 | jz 3f | ||
39 | st %r4,0(%r3) | ||
40 | 3: 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 | ||
3 | obj-vdso64 = gettimeofday.o clock_getres.o clock_gettime.o note.o | 3 | obj-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 | ||
31 | 0: sacf 0 | ||
32 | 1: sar %a4,%r1 | ||
33 | ltgr %r2,%r2 | ||
34 | jz 2f | ||
35 | st %r5,0(%r2) | ||
36 | 2: ltgr %r3,%r3 | ||
37 | jz 3f | ||
38 | st %r4,0(%r3) | ||
39 | 3: 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 | }; |