[RFC PATCH v2 6/9] x86: Prepare CPUs for post SKINIT launch

Sergii Dmytruk posted 9 patches 7 months, 2 weeks ago
[RFC PATCH v2 6/9] x86: Prepare CPUs for post SKINIT launch
Posted by Sergii Dmytruk 7 months, 2 weeks ago
From: Ross Philipson <ross.philipson@oracle.com>

The SKINIT instruction disables the GIF and it must be re-enabled
on the BSP and APs as they are started. Since enabling GIF also
re-enables NMIs, it should be done after a valid IDT is loaded for
each CPU.

SKINIT also already performed #INIT on the APs and it should be
bypassed before issuing the startup IPIs.

Signed-off-by: Ross Philipson <ross.philipson@oracle.com>
Signed-off-by: Sergii Dmytruk <sergii.dmytruk@3mdeb.com>
---
 arch/x86/kernel/slaunch.c | 23 +++++++++++++++++++++++
 arch/x86/kernel/smpboot.c | 15 ++++++++++++++-
 arch/x86/kernel/traps.c   |  4 ++++
 3 files changed, 41 insertions(+), 1 deletion(-)

diff --git a/arch/x86/kernel/slaunch.c b/arch/x86/kernel/slaunch.c
index 3a031043d2f1..a1c8be7de8d3 100644
--- a/arch/x86/kernel/slaunch.c
+++ b/arch/x86/kernel/slaunch.c
@@ -17,6 +17,7 @@
 #include <asm/sections.h>
 #include <asm/tlbflush.h>
 #include <asm/e820/api.h>
+#include <asm/svm.h>
 #include <asm/setup.h>
 #include <asm/svm.h>
 #include <asm/realmode.h>
@@ -716,3 +717,25 @@ void slaunch_finalize(int do_sexit)
 	else if (boot_cpu_has(X86_FEATURE_SKINIT))
 		slaunch_finalize_skinit();
 }
+
+/*
+ * AMD specific SKINIT CPU setup and initialization.
+ */
+void slaunch_cpu_setup_skinit(void)
+{
+	u64 val;
+
+	if (!slaunch_is_skinit_launch())
+		return;
+
+	/*
+	 * We don't yet handle #SX. Disable INIT_REDIRECTION first, before
+	 * enabling GIF, so a pending INIT resets us, rather than causing a
+	 * panic due to an unknown exception.
+	 */
+	rdmsrl(MSR_VM_CR, val);
+	wrmsrl(MSR_VM_CR, val & ~(1 << SVM_VM_CR_INIT_REDIRECTION));
+
+	/* Enable Global Interrupts flag */
+	asm volatile ("stgi" ::: "memory");
+}
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
index 219523884fdc..322fa4f8c5df 100644
--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -251,6 +251,12 @@ static void notrace __noendbr start_secondary(void *unused)
 
 	cpu_init_exception_handling(false);
 
+	/*
+	 * If this is an AMD SKINIT secure launch, some extra work is done
+	 * to prepare to start the secondary CPUs.
+	 */
+	slaunch_cpu_setup_skinit();
+
 	/*
 	 * Load the microcode before reaching the AP alive synchronization
 	 * point below so it is not part of the full per CPU serialized
@@ -703,7 +709,14 @@ static int wakeup_secondary_cpu_via_init(u32 phys_apicid, unsigned long start_ei
 
 	preempt_disable();
 	maxlvt = lapic_get_maxlvt();
-	send_init_sequence(phys_apicid);
+
+	/*
+	 * If this is an SKINIT secure launch, #INIT is already done on the APs
+	 * by issuing the SKINIT instruction. For security reasons #INIT
+	 * should not be done again.
+	 */
+	if (!slaunch_is_skinit_launch())
+		send_init_sequence(phys_apicid);
 
 	mb();
 
diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c
index 9f88b8a78e50..0a4d218a426b 100644
--- a/arch/x86/kernel/traps.c
+++ b/arch/x86/kernel/traps.c
@@ -43,6 +43,7 @@
 #include <linux/atomic.h>
 #include <linux/iommu.h>
 #include <linux/ubsan.h>
+#include <linux/slaunch.h>
 
 #include <asm/stacktrace.h>
 #include <asm/processor.h>
@@ -1564,5 +1565,8 @@ void __init trap_init(void)
 	if (!cpu_feature_enabled(X86_FEATURE_FRED))
 		idt_setup_traps();
 
+	/* If SKINIT was done on the BSP, this is the spot to enable GIF */
+	slaunch_cpu_setup_skinit();
+
 	cpu_init();
 }
-- 
2.49.0