From 7431e96b6b322993fbd027d104758bfde209aaf4 Mon Sep 17 00:00:00 2001
From: Sergio Lopez <slp@redhat.com>
Date: Thu, 20 Oct 2022 10:23:16 +0200
Subject: [PATCH 13/15] x86/sev: write AP reset vector

If a jump table can't be found, write the SEV-ES trampoline location
into the AP reset vector used by libkrun's qboot.

Signed-off-by: Sergio Lopez <slp@redhat.com>
---
 arch/x86/kernel/sev.c | 25 ++++++++++++++++++++++++-
 1 file changed, 24 insertions(+), 1 deletion(-)

diff --git a/arch/x86/kernel/sev.c b/arch/x86/kernel/sev.c
index b031244d6d2d..19e4964fcc93 100644
--- a/arch/x86/kernel/sev.c
+++ b/arch/x86/kernel/sev.c
@@ -1146,6 +1146,29 @@ void snp_set_wakeup_secondary_cpu(void)
 	apic->wakeup_secondary_cpu = wakeup_cpu_via_vmgexit;
 }
 
+#define KRUN_AP_RESET_VECTOR 0xfffffff4
+
+static int sev_es_setup_ap_reset_vector(struct real_mode_header *rmh)
+{
+	u16 startup_cs, startup_ip;
+	u16 __iomem *ap_reset_vector;
+
+	startup_cs = (u16)(rmh->trampoline_start >> 4);
+	startup_ip = (u16)(rmh->sev_es_trampoline_start -
+			   rmh->trampoline_start);
+
+	ap_reset_vector = ioremap_encrypted(KRUN_AP_RESET_VECTOR, 4);
+	if (!ap_reset_vector)
+		return -EIO;
+
+	writew(startup_ip, &ap_reset_vector[0]);
+	writew(startup_cs, &ap_reset_vector[1]);
+
+	iounmap(ap_reset_vector);
+
+	return 0;
+}
+
 int __init sev_es_setup_ap_jump_table(struct real_mode_header *rmh)
 {
 	u16 startup_cs, startup_ip;
@@ -1157,7 +1180,7 @@ int __init sev_es_setup_ap_jump_table(struct real_mode_header *rmh)
 
 	/* On UP guests there is no jump table so this is not a failure */
 	if (!jump_table_addr)
-		return 0;
+		return sev_es_setup_ap_reset_vector(rmh);
 
 	/* Check if AP Jump Table is page-aligned */
 	if (jump_table_addr & ~PAGE_MASK)
-- 
2.40.0

