Skip to content

Commit f242ac4

Browse files
committed
Merge tag 'x86-urgent-2026-03-29' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 fixes from Ingo Molnar: - Fix an early boot crash in AMD SEV-SNP guests, caused by incorrect FSGSBASE init ordering (Nikunj A Dadhania) - Remove X86_CR4_FRED from the CR4 pinned bits mask, to fix a race window during the bootup of SEV-{ES,SNP} or TDX guests, which can crash them if they trigger exceptions in that window (Borislav Petkov) - Fix early boot failures on SEV-ES/SNP guests, due to incorrect early GHCB access (Nikunj A Dadhania) - Add clarifying comment to the CRn pinning logic, to avoid future confusion & bugs (Peter Zijlstra) * tag 'x86-urgent-2026-03-29' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: x86/cpu: Add comment clarifying CRn pinning x86/fred: Fix early boot failures on SEV-ES/SNP guests x86/cpu: Remove X86_CR4_FRED from the CR4 pinned bits mask x86/cpu: Enable FSGSBASE early in cpu_init_exception_handling()
2 parents 47e3f23 + a3e93ca commit f242ac4

3 files changed

Lines changed: 46 additions & 7 deletions

File tree

arch/x86/coco/sev/noinstr.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,9 @@ noinstr struct ghcb *__sev_get_ghcb(struct ghcb_state *state)
121121

122122
WARN_ON(!irqs_disabled());
123123

124+
if (!sev_cfg.ghcbs_initialized)
125+
return boot_ghcb;
126+
124127
data = this_cpu_read(runtime_data);
125128
ghcb = &data->ghcb_page;
126129

@@ -164,6 +167,9 @@ noinstr void __sev_put_ghcb(struct ghcb_state *state)
164167

165168
WARN_ON(!irqs_disabled());
166169

170+
if (!sev_cfg.ghcbs_initialized)
171+
return;
172+
167173
data = this_cpu_read(runtime_data);
168174
ghcb = &data->ghcb_page;
169175

arch/x86/entry/entry_fred.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,16 @@ static noinstr void fred_extint(struct pt_regs *regs)
177177
}
178178
}
179179

180+
#ifdef CONFIG_AMD_MEM_ENCRYPT
181+
noinstr void exc_vmm_communication(struct pt_regs *regs, unsigned long error_code)
182+
{
183+
if (user_mode(regs))
184+
return user_exc_vmm_communication(regs, error_code);
185+
else
186+
return kernel_exc_vmm_communication(regs, error_code);
187+
}
188+
#endif
189+
180190
static noinstr void fred_hwexc(struct pt_regs *regs, unsigned long error_code)
181191
{
182192
/* Optimize for #PF. That's the only exception which matters performance wise */
@@ -207,6 +217,10 @@ static noinstr void fred_hwexc(struct pt_regs *regs, unsigned long error_code)
207217
#ifdef CONFIG_X86_CET
208218
case X86_TRAP_CP: return exc_control_protection(regs, error_code);
209219
#endif
220+
#ifdef CONFIG_AMD_MEM_ENCRYPT
221+
case X86_TRAP_VC: return exc_vmm_communication(regs, error_code);
222+
#endif
223+
210224
default: return fred_bad_type(regs, error_code);
211225
}
212226

arch/x86/kernel/cpu/common.c

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -433,7 +433,20 @@ static __always_inline void setup_lass(struct cpuinfo_x86 *c)
433433

434434
/* These bits should not change their value after CPU init is finished. */
435435
static const unsigned long cr4_pinned_mask = X86_CR4_SMEP | X86_CR4_SMAP | X86_CR4_UMIP |
436-
X86_CR4_FSGSBASE | X86_CR4_CET | X86_CR4_FRED;
436+
X86_CR4_FSGSBASE | X86_CR4_CET;
437+
438+
/*
439+
* The CR pinning protects against ROP on the 'mov %reg, %CRn' instruction(s).
440+
* Since you can ROP directly to these instructions (barring shadow stack),
441+
* any protection must follow immediately and unconditionally after that.
442+
*
443+
* Specifically, the CR[04] write functions below will have the value
444+
* validation controlled by the @cr_pinning static_branch which is
445+
* __ro_after_init, just like the cr4_pinned_bits value.
446+
*
447+
* Once set, an attacker will have to defeat page-tables to get around these
448+
* restrictions. Which is a much bigger ask than 'simple' ROP.
449+
*/
437450
static DEFINE_STATIC_KEY_FALSE_RO(cr_pinning);
438451
static unsigned long cr4_pinned_bits __ro_after_init;
439452

@@ -2050,12 +2063,6 @@ static void identify_cpu(struct cpuinfo_x86 *c)
20502063
setup_umip(c);
20512064
setup_lass(c);
20522065

2053-
/* Enable FSGSBASE instructions if available. */
2054-
if (cpu_has(c, X86_FEATURE_FSGSBASE)) {
2055-
cr4_set_bits(X86_CR4_FSGSBASE);
2056-
elf_hwcap2 |= HWCAP2_FSGSBASE;
2057-
}
2058-
20592066
/*
20602067
* The vendor-specific functions might have changed features.
20612068
* Now we do "generic changes."
@@ -2416,6 +2423,18 @@ void cpu_init_exception_handling(bool boot_cpu)
24162423
/* GHCB needs to be setup to handle #VC. */
24172424
setup_ghcb();
24182425

2426+
/*
2427+
* On CPUs with FSGSBASE support, paranoid_entry() uses
2428+
* ALTERNATIVE-patched RDGSBASE/WRGSBASE instructions. Secondary CPUs
2429+
* boot after alternatives are patched globally, so early exceptions
2430+
* execute patched code that depends on FSGSBASE. Enable the feature
2431+
* before any exceptions occur.
2432+
*/
2433+
if (cpu_feature_enabled(X86_FEATURE_FSGSBASE)) {
2434+
cr4_set_bits(X86_CR4_FSGSBASE);
2435+
elf_hwcap2 |= HWCAP2_FSGSBASE;
2436+
}
2437+
24192438
if (cpu_feature_enabled(X86_FEATURE_FRED)) {
24202439
/* The boot CPU has enabled FRED during early boot */
24212440
if (!boot_cpu)

0 commit comments

Comments
 (0)