Skip to content

Commit ff3cfcb

Browse files
committed
x86/smpboot: Fix the parallel bringup decision
The decision to allow parallel bringup of secondary CPUs checks CC_ATTR_GUEST_STATE_ENCRYPT to detect encrypted guests. Those cannot use parallel bootup because accessing the local APIC is intercepted and raises a #VC or #VE, which cannot be handled at that point. The check works correctly, but only for AMD encrypted guests. TDX does not set that flag. As there is no real connection between CC attributes and the inability to support parallel bringup, replace this with a generic control flag in x86_cpuinit and let SEV-ES and TDX init code disable it. Fixes: 0c7ffa3 ("x86/smpboot/64: Implement arch_cpuhp_init_parallel_bringup() and enable it") Reported-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Tested-by: Tom Lendacky <thomas.lendacky@amd.com> Tested-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com> Link: https://lore.kernel.org/r/87ilc9gd2d.ffs@tglx
1 parent 33e20b0 commit ff3cfcb

5 files changed

Lines changed: 32 additions & 17 deletions

File tree

arch/x86/coco/tdx/tdx.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -871,5 +871,16 @@ void __init tdx_early_init(void)
871871
x86_platform.guest.enc_tlb_flush_required = tdx_tlb_flush_required;
872872
x86_platform.guest.enc_status_change_finish = tdx_enc_status_changed;
873873

874+
/*
875+
* TDX intercepts the RDMSR to read the X2APIC ID in the parallel
876+
* bringup low level code. That raises #VE which cannot be handled
877+
* there.
878+
*
879+
* Intel-TDX has a secure RDMSR hypercall, but that needs to be
880+
* implemented seperately in the low level startup ASM code.
881+
* Until that is in place, disable parallel bringup for TDX.
882+
*/
883+
x86_cpuinit.parallel_bringup = false;
884+
874885
pr_info("Guest detected\n");
875886
}

arch/x86/include/asm/x86_init.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,11 +177,14 @@ struct x86_init_ops {
177177
* struct x86_cpuinit_ops - platform specific cpu hotplug setups
178178
* @setup_percpu_clockev: set up the per cpu clock event device
179179
* @early_percpu_clock_init: early init of the per cpu clock event device
180+
* @fixup_cpu_id: fixup function for cpuinfo_x86::phys_proc_id
181+
* @parallel_bringup: Parallel bringup control
180182
*/
181183
struct x86_cpuinit_ops {
182184
void (*setup_percpu_clockev)(void);
183185
void (*early_percpu_clock_init)(void);
184186
void (*fixup_cpu_id)(struct cpuinfo_x86 *c, int node);
187+
bool parallel_bringup;
185188
};
186189

187190
struct timespec64;

arch/x86/kernel/smpboot.c

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1267,23 +1267,8 @@ void __init smp_prepare_cpus_common(void)
12671267
/* Establish whether parallel bringup can be supported. */
12681268
bool __init arch_cpuhp_init_parallel_bringup(void)
12691269
{
1270-
/*
1271-
* Encrypted guests require special handling. They enforce X2APIC
1272-
* mode but the RDMSR to read the APIC ID is intercepted and raises
1273-
* #VC or #VE which cannot be handled in the early startup code.
1274-
*
1275-
* AMD-SEV does not provide a RDMSR GHCB protocol so the early
1276-
* startup code cannot directly communicate with the secure
1277-
* firmware. The alternative solution to retrieve the APIC ID via
1278-
* CPUID(0xb), which is covered by the GHCB protocol, is not viable
1279-
* either because there is no enforcement of the CPUID(0xb)
1280-
* provided "initial" APIC ID to be the same as the real APIC ID.
1281-
*
1282-
* Intel-TDX has a secure RDMSR hypercall, but that needs to be
1283-
* implemented seperately in the low level startup ASM code.
1284-
*/
1285-
if (cc_platform_has(CC_ATTR_GUEST_STATE_ENCRYPT)) {
1286-
pr_info("Parallel CPU startup disabled due to guest state encryption\n");
1270+
if (!x86_cpuinit.parallel_bringup) {
1271+
pr_info("Parallel CPU startup disabled by the platform\n");
12871272
return false;
12881273
}
12891274

arch/x86/kernel/x86_init.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ struct x86_init_ops x86_init __initdata = {
126126
struct x86_cpuinit_ops x86_cpuinit = {
127127
.early_percpu_clock_init = x86_init_noop,
128128
.setup_percpu_clockev = setup_secondary_APIC_clock,
129+
.parallel_bringup = true,
129130
};
130131

131132
static void default_nmi_init(void) { };

arch/x86/mm/mem_encrypt_amd.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -501,6 +501,21 @@ void __init sme_early_init(void)
501501
x86_platform.guest.enc_status_change_finish = amd_enc_status_change_finish;
502502
x86_platform.guest.enc_tlb_flush_required = amd_enc_tlb_flush_required;
503503
x86_platform.guest.enc_cache_flush_required = amd_enc_cache_flush_required;
504+
505+
/*
506+
* AMD-SEV-ES intercepts the RDMSR to read the X2APIC ID in the
507+
* parallel bringup low level code. That raises #VC which cannot be
508+
* handled there.
509+
* It does not provide a RDMSR GHCB protocol so the early startup
510+
* code cannot directly communicate with the secure firmware. The
511+
* alternative solution to retrieve the APIC ID via CPUID(0xb),
512+
* which is covered by the GHCB protocol, is not viable either
513+
* because there is no enforcement of the CPUID(0xb) provided
514+
* "initial" APIC ID to be the same as the real APIC ID.
515+
* Disable parallel bootup.
516+
*/
517+
if (sev_status & MSR_AMD64_SEV_ES_ENABLED)
518+
x86_cpuinit.parallel_bringup = false;
504519
}
505520

506521
void __init mem_encrypt_free_decrypted_mem(void)

0 commit comments

Comments
 (0)