aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIngo Molnar <mingo@kernel.org>2015-07-17 06:28:12 -0400
committerIngo Molnar <mingo@kernel.org>2015-07-17 21:42:51 -0400
commit5aaeb5c01c5b6c0be7b7aadbf3ace9f3a4458c3d (patch)
tree8cf45cdd6647d1067d94aaad64598a7728f15d6b
parent0c8c0f03e3a292e031596484275c14cf39c0ab7a (diff)
x86/fpu, sched: Introduce CONFIG_ARCH_WANTS_DYNAMIC_TASK_STRUCT and use it on x86
Don't burden architectures without dynamic task_struct sizing with the overhead of dynamic sizing. Also optimize the x86 code a bit by caching task_struct_size. Acked-and-Tested-by: Dave Hansen <dave.hansen@linux.intel.com> Cc: Andy Lutomirski <luto@amacapital.net> Cc: Borislav Petkov <bp@alien8.de> Cc: Brian Gerst <brgerst@gmail.com> Cc: Dave Hansen <dave@sr71.net> Cc: Denys Vlasenko <dvlasenk@redhat.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Oleg Nesterov <oleg@redhat.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Link: http://lkml.kernel.org/r/1437128892-9831-3-git-send-email-mingo@kernel.org Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r--arch/Kconfig4
-rw-r--r--arch/x86/Kconfig1
-rw-r--r--arch/x86/kernel/fpu/init.c17
-rw-r--r--arch/x86/kernel/process.c2
-rw-r--r--fs/proc/kcore.c4
-rw-r--r--include/linux/sched.h6
-rw-r--r--kernel/fork.c11
7 files changed, 27 insertions, 18 deletions
diff --git a/arch/Kconfig b/arch/Kconfig
index bec6666a3cc4..8a8ea7110de8 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -221,6 +221,10 @@ config ARCH_TASK_STRUCT_ALLOCATOR
221config ARCH_THREAD_INFO_ALLOCATOR 221config ARCH_THREAD_INFO_ALLOCATOR
222 bool 222 bool
223 223
224# Select if arch wants to size task_struct dynamically via arch_task_struct_size:
225config ARCH_WANTS_DYNAMIC_TASK_STRUCT
226 bool
227
224config HAVE_REGS_AND_STACK_ACCESS_API 228config HAVE_REGS_AND_STACK_ACCESS_API
225 bool 229 bool
226 help 230 help
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 3dbb7e7909ca..b3a1a5d77d92 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -41,6 +41,7 @@ config X86
41 select ARCH_USE_CMPXCHG_LOCKREF if X86_64 41 select ARCH_USE_CMPXCHG_LOCKREF if X86_64
42 select ARCH_USE_QUEUED_RWLOCKS 42 select ARCH_USE_QUEUED_RWLOCKS
43 select ARCH_USE_QUEUED_SPINLOCKS 43 select ARCH_USE_QUEUED_SPINLOCKS
44 select ARCH_WANTS_DYNAMIC_TASK_STRUCT
44 select ARCH_WANT_FRAME_POINTERS 45 select ARCH_WANT_FRAME_POINTERS
45 select ARCH_WANT_IPC_PARSE_VERSION if X86_32 46 select ARCH_WANT_IPC_PARSE_VERSION if X86_32
46 select ARCH_WANT_OPTIONAL_GPIOLIB 47 select ARCH_WANT_OPTIONAL_GPIOLIB
diff --git a/arch/x86/kernel/fpu/init.c b/arch/x86/kernel/fpu/init.c
index deacbfa6b33e..0b39173dd971 100644
--- a/arch/x86/kernel/fpu/init.c
+++ b/arch/x86/kernel/fpu/init.c
@@ -4,6 +4,8 @@
4#include <asm/fpu/internal.h> 4#include <asm/fpu/internal.h>
5#include <asm/tlbflush.h> 5#include <asm/tlbflush.h>
6 6
7#include <linux/sched.h>
8
7/* 9/*
8 * Initialize the TS bit in CR0 according to the style of context-switches 10 * Initialize the TS bit in CR0 according to the style of context-switches
9 * we are using: 11 * we are using:
@@ -136,16 +138,14 @@ static void __init fpu__init_system_generic(void)
136unsigned int xstate_size; 138unsigned int xstate_size;
137EXPORT_SYMBOL_GPL(xstate_size); 139EXPORT_SYMBOL_GPL(xstate_size);
138 140
139#define CHECK_MEMBER_AT_END_OF(TYPE, MEMBER) \ 141/* Enforce that 'MEMBER' is the last field of 'TYPE': */
140 BUILD_BUG_ON((sizeof(TYPE) - \ 142#define CHECK_MEMBER_AT_END_OF(TYPE, MEMBER) \
141 offsetof(TYPE, MEMBER) - \ 143 BUILD_BUG_ON(sizeof(TYPE) != offsetofend(TYPE, MEMBER))
142 sizeof(((TYPE *)0)->MEMBER)) > \
143 0) \
144 144
145/* 145/*
146 * We append the 'struct fpu' to the task_struct. 146 * We append the 'struct fpu' to the task_struct:
147 */ 147 */
148int __weak arch_task_struct_size(void) 148static void __init fpu__init_task_struct_size(void)
149{ 149{
150 int task_size = sizeof(struct task_struct); 150 int task_size = sizeof(struct task_struct);
151 151
@@ -172,7 +172,7 @@ int __weak arch_task_struct_size(void)
172 CHECK_MEMBER_AT_END_OF(struct thread_struct, fpu); 172 CHECK_MEMBER_AT_END_OF(struct thread_struct, fpu);
173 CHECK_MEMBER_AT_END_OF(struct task_struct, thread); 173 CHECK_MEMBER_AT_END_OF(struct task_struct, thread);
174 174
175 return task_size; 175 arch_task_struct_size = task_size;
176} 176}
177 177
178/* 178/*
@@ -326,6 +326,7 @@ void __init fpu__init_system(struct cpuinfo_x86 *c)
326 fpu__init_system_generic(); 326 fpu__init_system_generic();
327 fpu__init_system_xstate_size_legacy(); 327 fpu__init_system_xstate_size_legacy();
328 fpu__init_system_xstate(); 328 fpu__init_system_xstate();
329 fpu__init_task_struct_size();
329 330
330 fpu__init_system_ctx_switch(); 331 fpu__init_system_ctx_switch();
331} 332}
diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c
index 975420eac105..397688beed4b 100644
--- a/arch/x86/kernel/process.c
+++ b/arch/x86/kernel/process.c
@@ -81,7 +81,7 @@ EXPORT_SYMBOL_GPL(idle_notifier_unregister);
81 */ 81 */
82int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) 82int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
83{ 83{
84 memcpy(dst, src, arch_task_struct_size()); 84 memcpy(dst, src, arch_task_struct_size);
85 85
86 return fpu__copy(&dst->thread.fpu, &src->thread.fpu); 86 return fpu__copy(&dst->thread.fpu, &src->thread.fpu);
87} 87}
diff --git a/fs/proc/kcore.c b/fs/proc/kcore.c
index a0fe99485687..92e6726f6e37 100644
--- a/fs/proc/kcore.c
+++ b/fs/proc/kcore.c
@@ -92,7 +92,7 @@ static size_t get_kcore_size(int *nphdr, size_t *elf_buflen)
92 roundup(sizeof(CORE_STR), 4)) + 92 roundup(sizeof(CORE_STR), 4)) +
93 roundup(sizeof(struct elf_prstatus), 4) + 93 roundup(sizeof(struct elf_prstatus), 4) +
94 roundup(sizeof(struct elf_prpsinfo), 4) + 94 roundup(sizeof(struct elf_prpsinfo), 4) +
95 roundup(arch_task_struct_size(), 4); 95 roundup(arch_task_struct_size, 4);
96 *elf_buflen = PAGE_ALIGN(*elf_buflen); 96 *elf_buflen = PAGE_ALIGN(*elf_buflen);
97 return size + *elf_buflen; 97 return size + *elf_buflen;
98} 98}
@@ -415,7 +415,7 @@ static void elf_kcore_store_hdr(char *bufp, int nphdr, int dataoff)
415 /* set up the task structure */ 415 /* set up the task structure */
416 notes[2].name = CORE_STR; 416 notes[2].name = CORE_STR;
417 notes[2].type = NT_TASKSTRUCT; 417 notes[2].type = NT_TASKSTRUCT;
418 notes[2].datasz = arch_task_struct_size(); 418 notes[2].datasz = arch_task_struct_size;
419 notes[2].data = current; 419 notes[2].data = current;
420 420
421 nhdr->p_filesz += notesize(&notes[2]); 421 nhdr->p_filesz += notesize(&notes[2]);
diff --git a/include/linux/sched.h b/include/linux/sched.h
index e43a41d892b6..04b5ada460b4 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1786,7 +1786,11 @@ struct task_struct {
1786 */ 1786 */
1787}; 1787};
1788 1788
1789extern int arch_task_struct_size(void); 1789#ifdef CONFIG_ARCH_WANTS_DYNAMIC_TASK_STRUCT
1790extern int arch_task_struct_size __read_mostly;
1791#else
1792# define arch_task_struct_size (sizeof(struct task_struct))
1793#endif
1790 1794
1791/* Future-safe accessor for struct task_struct's cpus_allowed. */ 1795/* Future-safe accessor for struct task_struct's cpus_allowed. */
1792#define tsk_cpus_allowed(tsk) (&(tsk)->cpus_allowed) 1796#define tsk_cpus_allowed(tsk) (&(tsk)->cpus_allowed)
diff --git a/kernel/fork.c b/kernel/fork.c
index 431b67a6098c..dbd9b8d7b7cc 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -287,21 +287,20 @@ static void set_max_threads(unsigned int max_threads_suggested)
287 max_threads = clamp_t(u64, threads, MIN_THREADS, MAX_THREADS); 287 max_threads = clamp_t(u64, threads, MIN_THREADS, MAX_THREADS);
288} 288}
289 289
290int __weak arch_task_struct_size(void) 290#ifdef CONFIG_ARCH_WANTS_DYNAMIC_TASK_STRUCT
291{ 291/* Initialized by the architecture: */
292 return sizeof(struct task_struct); 292int arch_task_struct_size __read_mostly;
293} 293#endif
294 294
295void __init fork_init(void) 295void __init fork_init(void)
296{ 296{
297 int task_struct_size = arch_task_struct_size();
298#ifndef CONFIG_ARCH_TASK_STRUCT_ALLOCATOR 297#ifndef CONFIG_ARCH_TASK_STRUCT_ALLOCATOR
299#ifndef ARCH_MIN_TASKALIGN 298#ifndef ARCH_MIN_TASKALIGN
300#define ARCH_MIN_TASKALIGN L1_CACHE_BYTES 299#define ARCH_MIN_TASKALIGN L1_CACHE_BYTES
301#endif 300#endif
302 /* create a slab on which task_structs can be allocated */ 301 /* create a slab on which task_structs can be allocated */
303 task_struct_cachep = 302 task_struct_cachep =
304 kmem_cache_create("task_struct", task_struct_size, 303 kmem_cache_create("task_struct", arch_task_struct_size,
305 ARCH_MIN_TASKALIGN, SLAB_PANIC | SLAB_NOTRACK, NULL); 304 ARCH_MIN_TASKALIGN, SLAB_PANIC | SLAB_NOTRACK, NULL);
306#endif 305#endif
307 306