Commit 3f6813b9 authored by Martin Schwidefsky's avatar Martin Schwidefsky

s390/fpu: allocate 'struct fpu' with the task_struct

Analog to git commit 0c8c0f03
"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: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent c7d4d259
...@@ -107,6 +107,7 @@ config S390 ...@@ -107,6 +107,7 @@ config S390
select ARCH_SUPPORTS_NUMA_BALANCING select ARCH_SUPPORTS_NUMA_BALANCING
select ARCH_USE_BUILTIN_BSWAP select ARCH_USE_BUILTIN_BSWAP
select ARCH_USE_CMPXCHG_LOCKREF select ARCH_USE_CMPXCHG_LOCKREF
select ARCH_WANTS_DYNAMIC_TASK_STRUCT
select ARCH_WANTS_PROT_NUMA_PROT_NONE select ARCH_WANTS_PROT_NUMA_PROT_NONE
select ARCH_WANT_IPC_PARSE_VERSION select ARCH_WANT_IPC_PARSE_VERSION
select BUILDTIME_EXTABLE_SORT select BUILDTIME_EXTABLE_SORT
......
...@@ -11,11 +11,13 @@ ...@@ -11,11 +11,13 @@
#include <asm/sigcontext.h> #include <asm/sigcontext.h>
struct fpu { struct fpu {
__u32 fpc; /* Floating-point control */ __u32 fpc; /* Floating-point control */
void *regs; /* Pointer to the current save area */
union { union {
void *regs; /* Floating-point register save area */
freg_t *fprs; /* Floating-point register save area */ freg_t fprs[__NUM_FPRS];
__vector128 *vxrs; /* Vector register save area */ /* Vector register save area */
__vector128 vxrs[__NUM_VXRS];
}; };
}; };
......
...@@ -105,7 +105,6 @@ typedef struct { ...@@ -105,7 +105,6 @@ typedef struct {
* Thread structure * Thread structure
*/ */
struct thread_struct { struct thread_struct {
struct fpu fpu; /* FP and VX register save area */
unsigned int acrs[NUM_ACRS]; unsigned int acrs[NUM_ACRS];
unsigned long ksp; /* kernel stack pointer */ unsigned long ksp; /* kernel stack pointer */
mm_segment_t mm_segment; mm_segment_t mm_segment;
...@@ -120,6 +119,11 @@ struct thread_struct { ...@@ -120,6 +119,11 @@ struct thread_struct {
/* cpu runtime instrumentation */ /* cpu runtime instrumentation */
struct runtime_instr_cb *ri_cb; struct runtime_instr_cb *ri_cb;
unsigned char trap_tdb[256]; /* Transaction abort diagnose block */ unsigned char trap_tdb[256]; /* Transaction abort diagnose block */
/*
* Warning: 'fpu' is dynamically-sized. It *MUST* be at
* the end.
*/
struct fpu fpu; /* FP and VX register save area */
}; };
/* Flag to disable transactions. */ /* Flag to disable transactions. */
...@@ -155,10 +159,9 @@ struct stack_frame { ...@@ -155,10 +159,9 @@ struct stack_frame {
#define ARCH_MIN_TASKALIGN 8 #define ARCH_MIN_TASKALIGN 8
extern __vector128 init_task_fpu_regs[__NUM_VXRS];
#define INIT_THREAD { \ #define INIT_THREAD { \
.ksp = sizeof(init_stack) + (unsigned long) &init_stack, \ .ksp = sizeof(init_stack) + (unsigned long) &init_stack, \
.fpu.regs = (void *)&init_task_fpu_regs, \ .fpu.regs = (void *) init_task.thread.fpu.fprs, \
} }
/* /*
......
...@@ -37,9 +37,6 @@ ...@@ -37,9 +37,6 @@
asmlinkage void ret_from_fork(void) asm ("ret_from_fork"); asmlinkage void ret_from_fork(void) asm ("ret_from_fork");
/* FPU save area for the init task */
__vector128 init_task_fpu_regs[__NUM_VXRS] __init_task_data;
/* /*
* Return saved PC of a blocked thread. used in kernel/sched. * Return saved PC of a blocked thread. used in kernel/sched.
* resume in entry.S does not create a new stack frame, it * 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,35 +82,19 @@ void release_thread(struct task_struct *dead_task)
void arch_release_task_struct(struct task_struct *tsk) void arch_release_task_struct(struct task_struct *tsk)
{ {
/* Free either the floating-point or the vector register save area */
kfree(tsk->thread.fpu.regs);
} }
int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
{ {
size_t fpu_regs_size;
*dst = *src;
/*
* If the vector extension is available, it is enabled for all tasks,
* and, thus, the FPU register save area must be allocated accordingly.
*/
fpu_regs_size = MACHINE_HAS_VX ? sizeof(__vector128) * __NUM_VXRS
: sizeof(freg_t) * __NUM_FPRS;
dst->thread.fpu.regs = kzalloc(fpu_regs_size, GFP_KERNEL|__GFP_REPEAT);
if (!dst->thread.fpu.regs)
return -ENOMEM;
/* /*
* Save the floating-point or vector register state of the current * Save the floating-point or vector register state of the current
* task and set the CIF_FPU flag to lazy restore the FPU register * task and set the CIF_FPU flag to lazy restore the FPU register
* state when returning to user space. * state when returning to user space.
*/ */
save_fpu_regs(); save_fpu_regs();
dst->thread.fpu.fpc = current->thread.fpu.fpc;
memcpy(dst->thread.fpu.regs, current->thread.fpu.regs, fpu_regs_size);
memcpy(dst, src, arch_task_struct_size);
dst->thread.fpu.regs = dst->thread.fpu.fprs;
return 0; return 0;
} }
......
...@@ -808,6 +808,22 @@ static void __init setup_randomness(void) ...@@ -808,6 +808,22 @@ static void __init setup_randomness(void)
free_page((unsigned long) vmms); free_page((unsigned long) vmms);
} }
/*
* Find the correct size for the task_struct. This depends on
* the size of the struct fpu at the end of the thread_struct
* which is embedded in the task_struct.
*/
static void __init setup_task_size(void)
{
int task_size = sizeof(struct task_struct);
if (!MACHINE_HAS_VX) {
task_size -= sizeof(__vector128) * __NUM_VXRS;
task_size += sizeof(freg_t) * __NUM_FPRS;
}
arch_task_struct_size = task_size;
}
/* /*
* Setup function called from init/main.c just after the banner * Setup function called from init/main.c just after the banner
* was printed. * was printed.
...@@ -846,6 +862,7 @@ void __init setup_arch(char **cmdline_p) ...@@ -846,6 +862,7 @@ void __init setup_arch(char **cmdline_p)
os_info_init(); os_info_init();
setup_ipl(); setup_ipl();
setup_task_size();
/* Do some memory reservations *before* memory is added to memblock */ /* Do some memory reservations *before* memory is added to memblock */
reserve_memory_end(); reserve_memory_end();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment