Messages in this thread Patch in this message | | | Date | Fri, 17 Jul 2015 10:43:32 +0200 | From | Ingo Molnar <> | Subject | [PATCH] x86/fpu, bug.h: Move CHECK_MEMBER_AT_END_OF() to a generic header and use it in generic code |
| |
* Ingo Molnar <mingo@kernel.org> wrote:
> > * Peter Zijlstra <peterz@infradead.org> wrote: > > > On Thu, Jul 16, 2015 at 12:14:37PM -0700, Dave Hansen wrote: > > > +++ b/arch/x86/kernel/fpu/init.c 2015-07-16 12:02:15.284280976 -0700 > > > @@ -136,6 +136,45 @@ static void __init fpu__init_system_gene > > > unsigned int xstate_size; > > > EXPORT_SYMBOL_GPL(xstate_size); > > > > > > +#define CHECK_MEMBER_AT_END_OF(TYPE, MEMBER) \ > > > + BUILD_BUG_ON((sizeof(TYPE) - \ > > > + offsetof(TYPE, MEMBER) - \ > > > + sizeof(((TYPE *)0)->MEMBER)) > \ > > > + 0) \ > > > + > > > +/* > > > + * We append the 'struct fpu' to the task_struct. > > > + */ > > > +int __weak arch_task_struct_size(void) > > > +{ > > > + int task_size = sizeof(struct task_struct); > > > + > > > + /* > > > + * Subtract off the static size of the register state. > > > + * It potentially has a bunch of padding. > > > + */ > > > + task_size -= sizeof(((struct task_struct *)0)->thread.fpu.state); > > > + > > > + /* > > > + * Add back the dynamically-calculated register state > > > + * size. > > > + */ > > > + task_size += xstate_size; > > > + > > > + /* > > > + * We dynamically size 'struct fpu', so we require that > > > + * it be at the end of 'thread_struct' and that > > > + * 'thread_struct' be at the end of 'task_struct'. If > > > + * you hit a compile error here, check the structure to > > > + * see if something got added to the end. > > > + */ > > > + CHECK_MEMBER_AT_END_OF(struct fpu, state); > > > + CHECK_MEMBER_AT_END_OF(struct thread_struct, fpu); > > > + CHECK_MEMBER_AT_END_OF(struct task_struct, thread); > > > + > > > + return task_size; > > > +} > > > > Since you want these invariants true at all times, maybe put the > > BUILD_BUG_ON() in generic code instead of x86 specific? That way people > > poking at other archs are less likely to accidentally break your stuff. > > Yeah.
The patch below implements this. Only build tested.
Thanks,
Ingo
===============> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Ingo Molnar <mingo@kernel.org> --- arch/x86/kernel/fpu/init.c | 17 ++--------------- include/linux/bug.h | 4 ++++ kernel/fork.c | 18 ++++++++++++++++++ 3 files changed, 24 insertions(+), 15 deletions(-)
Index: tip/arch/x86/kernel/fpu/init.c =================================================================== --- tip.orig/arch/x86/kernel/fpu/init.c +++ tip/arch/x86/kernel/fpu/init.c @@ -136,16 +136,10 @@ static void __init fpu__init_system_gene unsigned int xstate_size; EXPORT_SYMBOL_GPL(xstate_size); -#define CHECK_MEMBER_AT_END_OF(TYPE, MEMBER) \ - BUILD_BUG_ON((sizeof(TYPE) - \ - offsetof(TYPE, MEMBER) - \ - sizeof(((TYPE *)0)->MEMBER)) > \ - 0) \ - /* * We append the 'struct fpu' to the task_struct. */ -int __weak arch_task_struct_size(void) +int arch_task_struct_size(void) { int task_size = sizeof(struct task_struct); @@ -161,16 +155,9 @@ int __weak arch_task_struct_size(void) */ task_size += xstate_size; - /* - * We dynamically size 'struct fpu', so we require that - * it be at the end of 'thread_struct' and that - * 'thread_struct' be at the end of 'task_struct'. If - * you hit a compile error here, check the structure to - * see if something got added to the end. - */ + /* Build time FPU structure layout debug checks: */ CHECK_MEMBER_AT_END_OF(struct fpu, state); CHECK_MEMBER_AT_END_OF(struct thread_struct, fpu); - CHECK_MEMBER_AT_END_OF(struct task_struct, thread); return task_size; } Index: tip/include/linux/bug.h =================================================================== --- tip.orig/include/linux/bug.h +++ tip/include/linux/bug.h @@ -85,6 +85,10 @@ struct pt_regs; #endif /* __CHECKER__ */ +/* Enforce that 'MEMBER' is the last field of 'TYPE': */ +#define CHECK_MEMBER_AT_END_OF(TYPE, MEMBER) \ + BUILD_BUG_ON(sizeof(TYPE) != offsetofend(TYPE, MEMBER)) + #ifdef CONFIG_GENERIC_BUG #include <asm-generic/bug.h> Index: tip/kernel/fork.c =================================================================== --- tip.orig/kernel/fork.c +++ tip/kernel/fork.c @@ -287,8 +287,26 @@ static void set_max_threads(unsigned int max_threads = clamp_t(u64, threads, MIN_THREADS, MAX_THREADS); } +#define CHECK_MEMBER_AT_END_OF(TYPE, MEMBER) \ + BUILD_BUG_ON(sizeof(TYPE) != offsetofend(TYPE, MEMBER)) + +/* + * This function can be overridden by the architecture to support dynamic sizing + * of the task_struct: + */ int __weak arch_task_struct_size(void) { + /* + * Build-time checks for structure layout constraints: + * + * On some architectures we dynamically size 'struct thread_struct', + * so we require that it be at the end of 'task_struct'. + * + * If you hit a compile error here, check the structure to + * see if something got added to the end. + */ + CHECK_MEMBER_AT_END_OF(struct task_struct, thread); + return sizeof(struct task_struct); }
| |