All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Nikunj A. Dadhania" <nikunj@amd.com>
To: Dave Hansen <dave.hansen@intel.com>,
	Tom Lendacky <thomas.lendacky@amd.com>,
	Borislav Petkov <bp@alien8.de>
Cc: <linux-kernel@vger.kernel.org>, <kvm@vger.kernel.org>,
	<tglx@kernel.org>, <mingo@redhat.com>,
	<dave.hansen@linux.intel.com>, <hpa@zytor.com>, <xin@zytor.com>,
	<seanjc@google.com>, <pbonzini@redhat.com>, <x86@kernel.org>,
	<sohil.mehta@intel.com>, <jon.grimm@amd.com>
Subject: Re: [PATCH v2 1/2] x86/cpu: Disable CR pinning during CPU bringup
Date: Wed, 11 Mar 2026 16:11:17 +0530	[thread overview]
Message-ID: <9fa61b80-0e16-4a87-a0e7-3c3dfcda8f7e@amd.com> (raw)
In-Reply-To: <505a6bbd-3ecf-4de9-8fb9-0b21c3435a96@intel.com>


On 3/10/2026 12:57 AM, Dave Hansen wrote:
> On 3/9/26 11:40, Tom Lendacky wrote:
>> The SNP guest is dying in __x2apic_enable() when trying to read
>> MSR_IA32_APICBASE, which will trigger a #VC.
>>
>> If I set CR4[16] in cr4_init() then the SNP guest boots fine.
> 
> That sounds pretty definitive.

Thanks Dave and Tom for the help to uncover CR4.FSGSBASE implicit dependency.

> How does this work on the boot CPU? How does it manage to get FSGSBASE
> set up before __x2apic_enable()? 

The boot CPU doesn't have FSGSBASE enabled before __x2apic_enable() either.

> Or is it on the early exception code, which might not use FSGSBASE instructions?

Correct. The key difference is timing relative to ALTERNATIVE patching. I added instrumentation to verify this behavior:

  Boot CPU sequence (without CR pinning disable patch):
     traps: trap_init() ENTRY: CR4.FSGSBASE=0, cpu=0
     traps: trap_init() AFTER cpu_init: CR4.FSGSBASE=0, cpu=0
     arch_cpu_finalize_init() ENTRY: CR4.FSGSBASE=0, cpu=0
     identify_boot_cpu() ENTRY: CR4.FSGSBASE=0, cpu=0
     identify_boot_cpu() EXIT: CR4.FSGSBASE=1, cpu=0
     SMP alternatives: BEFORE apply_alternatives: CR4.FSGSBASE=1, boot_cpu_has(FSGSBASE)=1, cpu=0
     SMP alternatives: Starting ALTERNATIVE patching

The boot CPU enables CR4.FSGSBASE in identify_boot_cpu() *before* ALTERNATIVE
patching occurs in alternative_instructions(). This means 

  cpu_init()
  -> x2apic_setup()
     -> __x2apic_enable()

executes unpatched paranoid_entry() code that uses RDMSR/SWAPGS instead of
RDGSBASE/WRGSBASE. Due to this, boot CPU does not have this problem.

  Secondary CPU sequence (without CR pinning disable patch):
     smpboot: start_secondary() BEFORE cr4_init: CR4.FSGSBASE=0, cpu=1
     cr4_init() ENTRY: CR4=0x10f0, FSGSBASE=0, cpu=1
     cr4_init() EXIT: CR4=0x10f0->0x3318f0, FSGSBASE=0->1, cpu=1, pinning=1

Secondary CPUs boot after alternatives have been applied globally. They
execute already-patched paranoid_entry() code that uses RDGSBASE/WRGSBASE
instructions, which require CR4.FSGSBASE=1.

Currently, secondary CPUs get CR4.FSGSBASE set implicitly through CR pinning.
The CR pinning disable patch removes this implicit setting, exposing the
hidden dependency. Without CR4.FSGSBASE enabled, RDGSBASE/WRGSBASE should
trigger #UD.

Note: I also verified the root cause by disabling the FSGSBASE ALTERNATIVE
patching, which forced the code to always use RDMSR/SWAPGS. With this change,
SNP guests boot successfully even without CR4.FSGSBASE set early, confirming
the issue is the timing between ALTERNATIVE patching (global) and CR4.FSGSBASE
enablement(per-CPU)
 
> Either way, I do think this needs to get fixed up. It was not acceptable
> for cr4_init() implicitly to set pinned features and then have the CPU
> boot code come along and do:
> 
> 	cr4_set_bits(X86_CR4_FSGSBASE);
> 
> It all basically worked by accident before.

Agreed. The attached pre-patch makes the dependency explicit by directly
enabling CR4.FSGSBASE in cr4_init() when the feature is available. This
ensures secondary CPUs have FSGSBASE enabled before any exceptions can
occur, regardless of CR pinning state:

  Secondary CPU sequence (with this patch):
    smpboot: start_secondary() BEFORE cr4_init: CR4.FSGSBASE=0, cpu=1
    cr4_init() ENTRY: CR4=0x10f0, FSGSBASE=0, cpu=1
    cr4_init() EXIT: CR4=0x10f0->0x310f0, FSGSBASE=0->1, cpu=1, pinning=0

-------------------------------------------------------------------------

From: Nikunj A Dadhania <nikunj@amd.com>
Subject: [PATCH] x86/cpu: Enable FSGSBASE early in cr4_init()

== Background ==

Exception entry code (paranoid_entry()) uses ALTERNATIVE patching based on
X86_FEATURE_FSGSBASE to decide whether to use RDGSBASE/WRGSBASE
instructions or the slower RDMSR/SWAPGS sequence for saving/restoring
GSBASE.

For boot cpu, ALTERNATIVE patching happens after enabling FSGSBASE in CR4.
When the feature is available, the code is permanently patched to use
RDGSBASE/WRGSBASE, which require CR4.FSGSBASE=1 to execute without
triggering #UD.

== Boot Sequence ==

Boot CPU (with CR pinning enabled):
  trap_init()
    cpu_init()                   <- Uses unpatched code (RDMSR/SWAPGS)
      x2apic_setup()
  ...
  arch_cpu_finalize_init()
    identify_boot_cpu()
      identify_cpu()
        cr4_set_bits(X86_CR4_FSGSBASE)  # Enables the feature
                                        # This becomes part of cr4_pinned_bits
    ...
    alternative_instructions()   <- Patches code to use RDGSBASE/WRGSBASE

Secondary CPUs (with CR pinning enabled):
  start_secondary()
    cr4_init()                   <- Code already patched, CR4.FSGSBASE=1
                                    set implicitly via cr4_pinned_bits

    cpu_init()                   <- exceptions work because FSGSBASE is
                                    already enabled

Secondary CPU (with CR pinning disabled):
  start_secondary()
    cr4_init()                   <- Code already patched, CR4.FSGSBASE=0
    cpu_init()
      x2apic_setup()
        rdmsrq(MSR_IA32_APICBASE)  <- Triggers #VC in SNP guests
          exc_vmm_communication()
            paranoid_entry()       <- Uses RDGSBASE with CR4.FSGSBASE=0
                                      (patched code)
    ...
    ap_starting()
      identify_secondary_cpu()
        identify_cpu()
	  cr4_set_bits(X86_CR4_FSGSBASE)  <- Enables the feature, which is
                                             too late

== CR Pinning ==

Currently, CR4.FSGSBASE is set implicitly through CR pinning: the boot CPU
sets it during identify_cpu(), it becomes part of cr4_pinned_bits, and
cr4_init() applies those pinned bits to secondary CPUs. This works but
creates an undocumented dependency between cr4_init() and the pinning
mechanism.

== Problem ==

Secondary CPUs boot after alternatives have been applied globally. They
execute already-patched paranoid_entry() code that uses RDGSBASE/WRGSBASE
instructions, which require CR4.FSGSBASE=1. Upcoming changes to CR pinning
behavior will break the implicit dependency, causing secondary CPUs to
generate #UD.

This issue manifests on AMD SEV-SNP guests, where the rdmsrq() in
x2apic_setup() triggers a #VC exception early during cpu_init(). The #VC
handler (exc_vmm_communication()) executes the patched paranoid_entry()
path. Without CR4.FSGSBASE enabled, RDGSBASE instructions trigger #UD.

== Fix ==

Make the dependency explicit by directly enabling CR4.FSGSBASE in
cr4_init() when the feature is available. This ensures secondary CPUs have
FSGSBASE enabled before any exceptions can occur, matching the boot CPU's
final state.

Fixes: c82965f9e530 ("x86/entry/64: Handle FSGSBASE enabled paranoid entry/exit")
Cc: stable@vger.kernel.org
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: Sohil Mehta <sohil.mehta@intel.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Reported-by: Borislav Petkov <bp@alien8.de>
Signed-off-by: Nikunj A Dadhania <nikunj@amd.com>
---
 arch/x86/kernel/cpu/common.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 1c3261cae40c..f5f9b242a983 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -502,6 +502,16 @@ void cr4_init(void)
 
 	if (boot_cpu_has(X86_FEATURE_PCID))
 		cr4 |= X86_CR4_PCIDE;
+
+	/*
+	 * Enable FSGSBASE if available. Exception entry code (paranoid_entry)
+	 * is patched to use RDGSBASE/WRGSBASE when this feature is present,
+	 * and those instructions require CR4.FSGSBASE=1. Secondary CPUs must
+	 * enable this before any exceptions occur.
+	 */
+	if (boot_cpu_has(X86_FEATURE_FSGSBASE))
+		cr4 |= X86_CR4_FSGSBASE;
+
 	if (static_branch_likely(&cr_pinning))
 		cr4 = (cr4 & ~cr4_pinned_mask) | cr4_pinned_bits;
 
-- 
2.48.1




  reply	other threads:[~2026-03-11 10:41 UTC|newest]

Thread overview: 36+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-02-26  9:23 [PATCH v2 0/2] x86/fred: Fix SEV-ES/SNP guest boot failures Nikunj A Dadhania
2026-02-26  9:23 ` [PATCH v2 1/2] x86/cpu: Disable CR pinning during CPU bringup Nikunj A Dadhania
2026-03-09 13:46   ` Borislav Petkov
2026-03-09 15:38     ` Dave Hansen
2026-03-09 16:15       ` Borislav Petkov
2026-03-09 18:03         ` Dave Hansen
2026-03-09 18:40           ` Tom Lendacky
2026-03-09 19:27             ` Dave Hansen
2026-03-11 10:41               ` Nikunj A. Dadhania [this message]
2026-03-11 14:07                 ` Dave Hansen
2026-03-11 15:42                   ` Nikunj A. Dadhania
2026-03-11 17:28                     ` Dave Hansen
2026-03-12  7:21                       ` Nikunj A. Dadhania
2026-03-12  7:26                         ` Nikunj A. Dadhania
2026-03-12 14:08                       ` Nikunj A. Dadhania
2026-03-12 14:20                         ` Dave Hansen
2026-03-12 14:53                           ` Nikunj A. Dadhania
2026-03-12 15:02                             ` Dave Hansen
2026-03-12 19:06                               ` David Laight
2026-03-16 20:27                           ` Chang S. Bae
2026-03-16 21:43                             ` Dave Hansen
2026-03-17  4:12                               ` Nikunj A. Dadhania
2026-03-17 14:26                                 ` Borislav Petkov
2026-03-17 15:31                                 ` Dave Hansen
2026-03-17 16:54                                   ` Borislav Petkov
2026-03-18  8:19                                     ` Nikunj A. Dadhania
2026-03-17 17:04                               ` Chang S. Bae
2026-03-17 17:51                                 ` Chang S. Bae
2026-03-12 18:09                         ` Sohil Mehta
2026-03-13  8:35                           ` Nikunj A. Dadhania
2026-03-13 18:05                             ` Sohil Mehta
2026-03-13 19:10                               ` Borislav Petkov
2026-03-17 17:06                             ` Chang S. Bae
2026-02-26  9:23 ` [PATCH v2 2/2] x86/fred: Fix early boot failures on SEV-ES/SNP guests Nikunj A Dadhania
2026-02-26 14:14   ` Tom Lendacky
2026-02-27  4:14     ` Nikunj A. Dadhania

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=9fa61b80-0e16-4a87-a0e7-3c3dfcda8f7e@amd.com \
    --to=nikunj@amd.com \
    --cc=bp@alien8.de \
    --cc=dave.hansen@intel.com \
    --cc=dave.hansen@linux.intel.com \
    --cc=hpa@zytor.com \
    --cc=jon.grimm@amd.com \
    --cc=kvm@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@redhat.com \
    --cc=pbonzini@redhat.com \
    --cc=seanjc@google.com \
    --cc=sohil.mehta@intel.com \
    --cc=tglx@kernel.org \
    --cc=thomas.lendacky@amd.com \
    --cc=x86@kernel.org \
    --cc=xin@zytor.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.