summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Schwidefsky <schwidefsky@de.ibm.com>2016-04-01 09:42:15 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2016-04-21 03:51:15 -0400
commit3f6813b9a5e0aaec162a10037c203771a1b2c110 (patch)
tree4c7ae317f66c97fe422485b7ec1981c804b0cb65
parentc7d4d259b7477866376435155eb0ccdaee880677 (diff)
s390/fpu: allocate 'struct fpu' with the task_struct
Analog to git commit 0c8c0f03e3a292e031596484275c14cf39c0ab7a "x86/fpu, sched: Dynamically allocate 'struct fpu'" move the struct fpu to the end of the struct thread_struct, set CONFIG_ARCH_WANTS_DYNAMIC_TASK_STRUCT and add the setup_task_size() function to calculate the correct size fo the task struct. For the performance_defconfig this increases the size of struct task_struct from 7424 bytes to 7936 bytes (MACHINE_HAS_VX==1) or 7552 bytes (MACHINE_HAS_VX==0). The dynamic allocation of the struct fpu is removed. The slab cache uses an 8KB block for the task struct in all cases, there is enough room for the struct fpu. For MACHINE_HAS_VX==1 each task now needs 512 bytes less memory. Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
-rw-r--r--arch/s390/Kconfig1
-rw-r--r--arch/s390/include/asm/fpu/types.h10
-rw-r--r--arch/s390/include/asm/processor.h9
-rw-r--r--arch/s390/kernel/process.c23
-rw-r--r--arch/s390/kernel/setup.c17
5 files changed, 32 insertions, 28 deletions
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index bf24ab188921..212f34b2a58e 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -107,6 +107,7 @@ config S390
107 select ARCH_SUPPORTS_NUMA_BALANCING 107 select ARCH_SUPPORTS_NUMA_BALANCING
108 select ARCH_USE_BUILTIN_BSWAP 108 select ARCH_USE_BUILTIN_BSWAP
109 select ARCH_USE_CMPXCHG_LOCKREF 109 select ARCH_USE_CMPXCHG_LOCKREF
110 select ARCH_WANTS_DYNAMIC_TASK_STRUCT
110 select ARCH_WANTS_PROT_NUMA_PROT_NONE 111 select ARCH_WANTS_PROT_NUMA_PROT_NONE
111 select ARCH_WANT_IPC_PARSE_VERSION 112 select ARCH_WANT_IPC_PARSE_VERSION
112 select BUILDTIME_EXTABLE_SORT 113 select BUILDTIME_EXTABLE_SORT
diff --git a/arch/s390/include/asm/fpu/types.h b/arch/s390/include/asm/fpu/types.h
index 14a8b0c14f87..fe937c9b6471 100644
--- a/arch/s390/include/asm/fpu/types.h
+++ b/arch/s390/include/asm/fpu/types.h
@@ -11,11 +11,13 @@
11#include <asm/sigcontext.h> 11#include <asm/sigcontext.h>
12 12
13struct fpu { 13struct fpu {
14 __u32 fpc; /* Floating-point control */ 14 __u32 fpc; /* Floating-point control */
15 void *regs; /* Pointer to the current save area */
15 union { 16 union {
16 void *regs; 17 /* Floating-point register save area */
17 freg_t *fprs; /* Floating-point register save area */ 18 freg_t fprs[__NUM_FPRS];
18 __vector128 *vxrs; /* Vector register save area */ 19 /* Vector register save area */
20 __vector128 vxrs[__NUM_VXRS];
19 }; 21 };
20}; 22};
21 23
diff --git a/arch/s390/include/asm/processor.h b/arch/s390/include/asm/processor.h
index d6fd22ea270d..332f4f7dc8d3 100644
--- a/arch/s390/include/asm/processor.h
+++ b/arch/s390/include/asm/processor.h
@@ -105,7 +105,6 @@ typedef struct {
105 * Thread structure 105 * Thread structure
106 */ 106 */
107struct thread_struct { 107struct thread_struct {
108 struct fpu fpu; /* FP and VX register save area */
109 unsigned int acrs[NUM_ACRS]; 108 unsigned int acrs[NUM_ACRS];
110 unsigned long ksp; /* kernel stack pointer */ 109 unsigned long ksp; /* kernel stack pointer */
111 mm_segment_t mm_segment; 110 mm_segment_t mm_segment;
@@ -120,6 +119,11 @@ struct thread_struct {
120 /* cpu runtime instrumentation */ 119 /* cpu runtime instrumentation */
121 struct runtime_instr_cb *ri_cb; 120 struct runtime_instr_cb *ri_cb;
122 unsigned char trap_tdb[256]; /* Transaction abort diagnose block */ 121 unsigned char trap_tdb[256]; /* Transaction abort diagnose block */
122 /*
123 * Warning: 'fpu' is dynamically-sized. It *MUST* be at
124 * the end.
125 */
126 struct fpu fpu; /* FP and VX register save area */
123}; 127};
124 128
125/* Flag to disable transactions. */ 129/* Flag to disable transactions. */
@@ -155,10 +159,9 @@ struct stack_frame {
155 159
156#define ARCH_MIN_TASKALIGN 8 160#define ARCH_MIN_TASKALIGN 8
157 161
158extern __vector128 init_task_fpu_regs[__NUM_VXRS];
159#define INIT_THREAD { \ 162#define INIT_THREAD { \
160 .ksp = sizeof(init_stack) + (unsigned long) &init_stack, \ 163 .ksp = sizeof(init_stack) + (unsigned long) &init_stack, \
161 .fpu.regs = (void *)&init_task_fpu_regs, \ 164 .fpu.regs = (void *) init_task.thread.fpu.fprs, \
162} 165}
163 166
164/* 167/*
diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c
index 2bba7df4ac51..adb346b70166 100644
--- a/arch/s390/kernel/process.c
+++ b/arch/s390/kernel/process.c
@@ -37,9 +37,6 @@
37 37
38asmlinkage void ret_from_fork(void) asm ("ret_from_fork"); 38asmlinkage void ret_from_fork(void) asm ("ret_from_fork");
39 39
40/* FPU save area for the init task */
41__vector128 init_task_fpu_regs[__NUM_VXRS] __init_task_data;
42
43/* 40/*
44 * Return saved PC of a blocked thread. used in kernel/sched. 41 * Return saved PC of a blocked thread. used in kernel/sched.
45 * resume in entry.S does not create a new stack frame, it 42 * resume in entry.S does not create a new stack frame, it
@@ -85,35 +82,19 @@ void release_thread(struct task_struct *dead_task)
85 82
86void arch_release_task_struct(struct task_struct *tsk) 83void arch_release_task_struct(struct task_struct *tsk)
87{ 84{
88 /* Free either the floating-point or the vector register save area */
89 kfree(tsk->thread.fpu.regs);
90} 85}
91 86
92int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) 87int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
93{ 88{
94 size_t fpu_regs_size;
95
96 *dst = *src;
97
98 /*
99 * If the vector extension is available, it is enabled for all tasks,
100 * and, thus, the FPU register save area must be allocated accordingly.
101 */
102 fpu_regs_size = MACHINE_HAS_VX ? sizeof(__vector128) * __NUM_VXRS
103 : sizeof(freg_t) * __NUM_FPRS;
104 dst->thread.fpu.regs = kzalloc(fpu_regs_size, GFP_KERNEL|__GFP_REPEAT);
105 if (!dst->thread.fpu.regs)
106 return -ENOMEM;
107
108 /* 89 /*
109 * Save the floating-point or vector register state of the current 90 * Save the floating-point or vector register state of the current
110 * task and set the CIF_FPU flag to lazy restore the FPU register 91 * task and set the CIF_FPU flag to lazy restore the FPU register
111 * state when returning to user space. 92 * state when returning to user space.
112 */ 93 */
113 save_fpu_regs(); 94 save_fpu_regs();
114 dst->thread.fpu.fpc = current->thread.fpu.fpc;
115 memcpy(dst->thread.fpu.regs, current->thread.fpu.regs, fpu_regs_size);
116 95
96 memcpy(dst, src, arch_task_struct_size);
97 dst->thread.fpu.regs = dst->thread.fpu.fprs;
117 return 0; 98 return 0;
118} 99}
119 100
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index d3f9688f26b5..f31939147ccd 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -809,6 +809,22 @@ static void __init setup_randomness(void)
809} 809}
810 810
811/* 811/*
812 * Find the correct size for the task_struct. This depends on
813 * the size of the struct fpu at the end of the thread_struct
814 * which is embedded in the task_struct.
815 */
816static void __init setup_task_size(void)
817{
818 int task_size = sizeof(struct task_struct);
819
820 if (!MACHINE_HAS_VX) {
821 task_size -= sizeof(__vector128) * __NUM_VXRS;
822 task_size += sizeof(freg_t) * __NUM_FPRS;
823 }
824 arch_task_struct_size = task_size;
825}
826
827/*
812 * Setup function called from init/main.c just after the banner 828 * Setup function called from init/main.c just after the banner
813 * was printed. 829 * was printed.
814 */ 830 */
@@ -846,6 +862,7 @@ void __init setup_arch(char **cmdline_p)
846 862
847 os_info_init(); 863 os_info_init();
848 setup_ipl(); 864 setup_ipl();
865 setup_task_size();
849 866
850 /* Do some memory reservations *before* memory is added to memblock */ 867 /* Do some memory reservations *before* memory is added to memblock */
851 reserve_memory_end(); 868 reserve_memory_end();