summaryrefslogtreecommitdiff
path: root/arch/x86/kernel/apic
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/kernel/apic')
-rw-r--r--arch/x86/kernel/apic/apic.c3
-rw-r--r--arch/x86/kernel/apic/x2apic_savic.c35
2 files changed, 38 insertions, 0 deletions
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
index ff4029b57e95..7874284c1ca7 100644
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -1501,6 +1501,9 @@ static void setup_local_APIC(void)
return;
}
+ if (apic->setup)
+ apic->setup();
+
/*
* If this comes from kexec/kcrash the APIC might be enabled in
* SPIV. Soft disable it before doing further initialization.
diff --git a/arch/x86/kernel/apic/x2apic_savic.c b/arch/x86/kernel/apic/x2apic_savic.c
index bea844f28192..948d89497baa 100644
--- a/arch/x86/kernel/apic/x2apic_savic.c
+++ b/arch/x86/kernel/apic/x2apic_savic.c
@@ -8,17 +8,47 @@
*/
#include <linux/cc_platform.h>
+#include <linux/percpu-defs.h>
#include <asm/apic.h>
#include <asm/sev.h>
#include "local.h"
+struct secure_avic_page {
+ u8 regs[PAGE_SIZE];
+} __aligned(PAGE_SIZE);
+
+static struct secure_avic_page __percpu *savic_page __ro_after_init;
+
static int savic_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
{
return x2apic_enabled() && cc_platform_has(CC_ATTR_SNP_SECURE_AVIC);
}
+static void savic_setup(void)
+{
+ void *ap = this_cpu_ptr(savic_page);
+ enum es_result res;
+ unsigned long gpa;
+
+ gpa = __pa(ap);
+
+ /*
+ * The NPT entry for a vCPU's APIC backing page must always be
+ * present when the vCPU is running in order for Secure AVIC to
+ * function. A VMEXIT_BUSY is returned on VMRUN and the vCPU cannot
+ * be resumed if the NPT entry for the APIC backing page is not
+ * present. Notify GPA of the vCPU's APIC backing page to the
+ * hypervisor by calling savic_register_gpa(). Before executing
+ * VMRUN, the hypervisor makes use of this information to make sure
+ * the APIC backing page is mapped in NPT.
+ */
+ res = savic_register_gpa(gpa);
+ if (res != ES_OK)
+ snp_abort();
+}
+
static int savic_probe(void)
{
if (!cc_platform_has(CC_ATTR_SNP_SECURE_AVIC))
@@ -30,6 +60,10 @@ static int savic_probe(void)
/* unreachable */
}
+ savic_page = alloc_percpu(struct secure_avic_page);
+ if (!savic_page)
+ snp_abort();
+
return 1;
}
@@ -38,6 +72,7 @@ static struct apic apic_x2apic_savic __ro_after_init = {
.name = "secure avic x2apic",
.probe = savic_probe,
.acpi_madt_oem_check = savic_acpi_madt_oem_check,
+ .setup = savic_setup,
.dest_mode_logical = false,