Re: [PATCH v2 1/2] x86/cpu: Disable CR pinning during CPU bringup
From: Dave Hansen
Date: Mon Mar 09 2026 - 14:10:05 EST
On 3/9/26 09:15, Borislav Petkov wrote:
> On Mon, Mar 09, 2026 at 08:38:10AM -0700, Dave Hansen wrote:
>> On 3/9/26 06:46, Borislav Petkov wrote:
>>> My SNP guest stops booting with this right:
>> Could you dump out CR4 at wakeup_cpu_via_vmgexit() before and after this
>> patch? Right here:
>>
>> /* CR4 should maintain the MCE value */
>> cr4 = native_read_cr4() & X86_CR4_MCE;
>>
>> It's got to be some delta there.
> Looks the same to me:
>
> before: 31 SEV: wakeup_cpu_via_vmgexit: CR4: 0x3506f0
>
> That's 31 CPUs - no BSP with the CR4 value above.
>
> after: [ 3.354326] SEV: wakeup_cpu_via_vmgexit: CR4: 0x3506f0
>
> That stops after CPU1, i.e., the first AP. But the CR4 value is the same.
The only pinned bits in there are: SMAP, SMEP and FSGSBASE.
SMAP and SMEP are unlikely to be biting us here.
FSGSBASE is _possible_ but I don't see any of the {RD,WR}{F,G}SBASE
instructions in early boot where it would bite us.
Can you boot this thing without FSGSBASE support?
The other option would be to boot a working system, normally and see
what is getting flipped by pinning at cr4_init(). The attached patch
does that. It also uses trace_printk() so it hopefully won't trip over
#VC's during early boot with the console.
For me, it's flipping on 0x310800, which is:
#define X86_CR4_OSXMMEXCPT (1ul << 10)
#define X86_CR4_FSGSBASE (1ul << 16)
#define X86_CR4_SMEP (1ul << 20)
#define X86_CR4_SMAP (1ul << 21)
*Maybe* the paranoid entry code is getting called from the #VC handler
in early boot? It has ALTERNATIVEs on X86_FEATURE_FSGSBASE and might be
using the FSGSBASE instructions in there.
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 02472fc763d9b..cc408ec818870 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -501,12 +501,20 @@ EXPORT_SYMBOL_FOR_KVM(cr4_read_shadow);
void cr4_init(void)
{
unsigned long cr4 = __read_cr4();
+ unsigned long prepin_cr4;
if (boot_cpu_has(X86_FEATURE_PCID))
cr4 |= X86_CR4_PCIDE;
+ prepin_cr4 = cr4;
if (static_branch_likely(&cr_pinning))
cr4 = (cr4 & ~cr4_pinned_mask) | cr4_pinned_bits;
+ if (prepin_cr4 != cr4) {
+ trace_printk(" prepin_cr4: 0x%016lx\n", prepin_cr4);
+ trace_printk(" cr4: 0x%016lx\n", cr4);
+ trace_printk("cr4_pinned_mask: 0x%016lx\n", cr4_pinned_mask);
+ trace_printk("cr4_pinned_bits: 0x%016lx\n", cr4_pinned_bits);
+ }
__write_cr4(cr4);
/* Initialize cr4 shadow for this CPU. */