All of lore.kernel.org
 help / color / mirror / Atom feed
From: Ingo Molnar <mingo@kernel.org>
To: Oleg Nesterov <oleg@redhat.com>
Cc: Nathan Chancellor <nathan@kernel.org>,
	linux-kernel@vger.kernel.org,
	Andy Lutomirski <luto@amacapital.net>,
	Andrew Morton <akpm@linux-foundation.org>,
	Dave Hansen <dave@sr71.net>,
	Peter Zijlstra <peterz@infradead.org>,
	Borislav Petkov <bp@alien8.de>, Brian Gerst <brgerst@gmail.com>,
	"H . Peter Anvin" <hpa@zytor.com>,
	Linus Torvalds <torvalds@linux-foundation.org>,
	Thomas Gleixner <tglx@linutronix.de>,
	Uros Bizjak <ubizjak@gmail.com>
Subject: [PATCH 10/9] x86/fpu: Fix 'struct fpu' misalignment on 32-bit kernels
Date: Thu, 13 Jun 2024 11:36:38 +0200	[thread overview]
Message-ID: <Zmq9ppuIZJ9IMZDr@gmail.com> (raw)
In-Reply-To: <20240612184148.GB23973@redhat.com>


* Oleg Nesterov <oleg@redhat.com> wrote:

> The patch below seems to fix the problem.
> 
> Again, the changes in fpu__init_system_early_generic() are not
> strictly needed to fix it, but I believe make sense anyway.
> 
> Oleg.
> 
> 
> diff --git a/arch/x86/kernel/fpu/init.c b/arch/x86/kernel/fpu/init.c
> index 4e8d37b5a90b..848ea79886ba 100644
> --- a/arch/x86/kernel/fpu/init.c
> +++ b/arch/x86/kernel/fpu/init.c
> @@ -71,16 +71,14 @@ static bool __init fpu__probe_without_cpuid(void)
>  	return fsw == 0 && (fcw & 0x103f) == 0x003f;
>  }
>  
> -static struct fpu x86_init_fpu __read_mostly;
> +static struct fpu x86_init_fpu __attribute__ ((aligned (64))) __read_mostly;
>  
>  static void __init fpu__init_system_early_generic(void)
>  {
> -	int this_cpu = smp_processor_id();
> -
>  	fpstate_reset(&x86_init_fpu);
>  	current->thread.fpu = &x86_init_fpu;
> -	per_cpu(fpu_fpregs_owner_ctx, this_cpu) = &x86_init_fpu;
> -	x86_init_fpu.last_cpu = this_cpu;
> +	set_thread_flag(TIF_NEED_FPU_LOAD);
> +	x86_init_fpu.last_cpu = -1;
>  
>  	if (!boot_cpu_has(X86_FEATURE_CPUID) &&
>  	    !test_bit(X86_FEATURE_FPU, (unsigned long *)cpu_caps_cleared)) {
> diff --git a/include/linux/sched.h b/include/linux/sched.h
> index 215a7380e41c..ec22b9bf27f5 100644
> --- a/include/linux/sched.h
> +++ b/include/linux/sched.h
> @@ -1562,7 +1562,7 @@ struct task_struct {
>  	 * they are included in the randomized portion of task_struct.
>  	 */
>  	randomized_struct_fields_end
> -};
> +} __attribute__ ((aligned (64)));

Oh ... indeed, FPU context save area must be 64 bytes aligned!

On 64-bit kernels this was a given, accidentally, but on 32-bit kernels 
init_task was only 32-byte aligned:

  c22f04e0 D init_task

... which misaligned the struct fpu as well, I think. With your fix:

  c22f0500 D init_task

What happened is that due to my series 'struct task_struct' lost its 
64-byte alignment attribute, which broke the fpu struct allocation code on 
32-bit kernels and made the 64-bit one probably unrobust as well.

To add insult to injury, I was aware of the alignment requirement, and 
tried to cover it with an assert, but doubly mis-coded it:

+       BUILD_BUG_ON(sizeof(*dst) % SMP_CACHE_BYTES != 0);

Which is buggy:

 - As on 32-bit kernels CONFIG_X86_L1_CACHE_SHIFT=5, ie. 32 bytes ...

 - Nor does it really check the alignment of the FPU context save area 
   within struct fpu as it's allocated after task_struct ...

The interim patch below against the full WIP.x86/fpu series is what fixes 
Nathan's 32-bit testcase.

Further improvements:

 - The extra alignment attribute in <linux/sched.h> will affect other 
   architecture as well, although in practice the alignment of init_task is 
   not critical, and is very likely at least 32 bytes, probably more. 
   Still, it's a bit ugly in its current form.

 - Also, because this was pretty hard to debug, we should probably add an 
   alignment check to fpu__init_task_struct_size() where we allocate the 
   fpu context structure, and fix the buggy size-assert.

Thanks a lot for your help Oleg! I've added this tag of yours:

  Fixed-by: Oleg Nesterov <oleg@redhat.com>

... and would appreciate your Acked-by or Reviewed-by for the eventual 
final version of the series, but I don't insist. ;-)

	Ingo

=================>
diff --git a/arch/x86/kernel/fpu/init.c b/arch/x86/kernel/fpu/init.c
index 53580e59e5db..16b6611634c3 100644
--- a/arch/x86/kernel/fpu/init.c
+++ b/arch/x86/kernel/fpu/init.c
@@ -71,15 +71,13 @@ static bool __init fpu__probe_without_cpuid(void)
 	return fsw == 0 && (fcw & 0x103f) == 0x003f;
 }
 
-static struct fpu x86_init_fpu __read_mostly;
+static struct fpu x86_init_fpu __attribute__ ((aligned (64))) __read_mostly;
 
 static void __init fpu__init_system_early_generic(void)
 {
-	int this_cpu = smp_processor_id();
-
 	fpstate_reset(&x86_init_fpu);
-	per_cpu(fpu_fpregs_owner_ctx, this_cpu) = &x86_init_fpu;
-	x86_init_fpu.last_cpu = this_cpu;
+	set_thread_flag(TIF_NEED_FPU_LOAD);
+	x86_init_fpu.last_cpu = -1;
 
 	if (!boot_cpu_has(X86_FEATURE_CPUID) &&
 	    !test_bit(X86_FEATURE_FPU, (unsigned long *)cpu_caps_cleared)) {
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 215a7380e41c..ec22b9bf27f5 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1562,7 +1562,7 @@ struct task_struct {
 	 * they are included in the randomized portion of task_struct.
 	 */
 	randomized_struct_fields_end
-};
+} __attribute__ ((aligned (64)));
 
 #define TASK_REPORT_IDLE	(TASK_REPORT + 1)
 #define TASK_REPORT_MAX		(TASK_REPORT_IDLE << 1)

  parent reply	other threads:[~2024-06-13  9:36 UTC|newest]

Thread overview: 21+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-06-08  7:31 [PATCH 00/10, -v4] x86/fpu: Remove thread::fpu Ingo Molnar
2024-06-08  7:31 ` [PATCH 1/9] x86/fpu: Introduce the x86_task_fpu() helper method Ingo Molnar
2024-06-08  7:31 ` [PATCH 2/9] x86/fpu: Convert task_struct::thread.fpu accesses to use x86_task_fpu() Ingo Molnar
2024-06-08  7:31 ` [PATCH 3/9] x86/fpu: Make task_struct::thread constant size Ingo Molnar
2024-06-10 21:13   ` Nathan Chancellor
2024-06-11 12:42     ` Oleg Nesterov
2024-06-12  8:17       ` Ingo Molnar
2024-06-12  9:40         ` Oleg Nesterov
2024-06-12 18:41         ` Oleg Nesterov
2024-06-12 20:30           ` Oleg Nesterov
2024-06-13  9:36           ` Ingo Molnar [this message]
2024-06-14 15:16             ` [PATCH 10/9] x86/fpu: Fix 'struct fpu' misalignment on 32-bit kernels Oleg Nesterov
2024-06-15 10:23               ` Oleg Nesterov
2024-06-16 10:55                 ` Oleg Nesterov
2024-06-08  7:31 ` [PATCH 4/9] x86/fpu: Remove the thread::fpu pointer Ingo Molnar
2024-06-08  7:31 ` [PATCH 5/9] x86/fpu: Push 'fpu' pointer calculation into the fpu__drop() call Ingo Molnar
2024-06-08  7:31 ` [PATCH 6/9] x86/fpu: Make sure x86_task_fpu() doesn't get called for PF_KTHREAD tasks during exit Ingo Molnar
2024-06-10 10:01   ` Oleg Nesterov
2024-06-08  7:31 ` [PATCH 7/9] x86/fpu: Remove init_task FPU state dependencies, add debugging warning for PF_KTHREAD tasks Ingo Molnar
2024-06-08  7:31 ` [PATCH 8/9] x86/fpu: Use 'fpstate' variable names consistently Ingo Molnar
2024-06-08  7:31 ` [PATCH 9/9] x86/fpu: Fix stale comment in ex_handler_fprestore() Ingo Molnar

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=Zmq9ppuIZJ9IMZDr@gmail.com \
    --to=mingo@kernel.org \
    --cc=akpm@linux-foundation.org \
    --cc=bp@alien8.de \
    --cc=brgerst@gmail.com \
    --cc=dave@sr71.net \
    --cc=hpa@zytor.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=luto@amacapital.net \
    --cc=nathan@kernel.org \
    --cc=oleg@redhat.com \
    --cc=peterz@infradead.org \
    --cc=tglx@linutronix.de \
    --cc=torvalds@linux-foundation.org \
    --cc=ubizjak@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.