]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
x86/apic: Add support to send NMI IPI for Secure AVIC
authorNeeraj Upadhyay <Neeraj.Upadhyay@amd.com>
Thu, 28 Aug 2025 11:12:13 +0000 (16:42 +0530)
committerBorislav Petkov (AMD) <bp@alien8.de>
Mon, 1 Sep 2025 10:49:25 +0000 (12:49 +0200)
Secure AVIC introduces a new field in the APIC backing page "NmiReq" that has
to be set by the guest to request a NMI IPI through APIC_ICR write.

Add support to set NmiReq appropriately to send NMI IPI.

Co-developed-by: Kishon Vijay Abraham I <kvijayab@amd.com>
Signed-off-by: Kishon Vijay Abraham I <kvijayab@amd.com>
Signed-off-by: Neeraj Upadhyay <Neeraj.Upadhyay@amd.com>
Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
Reviewed-by: Tianyu Lan <tiala@microsoft.com>
Link: https://lore.kernel.org/20250828111213.208933-1-Neeraj.Upadhyay@amd.com
arch/x86/kernel/apic/x2apic_savic.c

index bdefe4cd4e29255a783eb66f2ada0de2a928d1a2..8ed56e87c32f6fda2b2591068ed2789fab519016 100644 (file)
@@ -133,12 +133,15 @@ static inline void self_ipi_reg_write(unsigned int vector)
        native_apic_msr_write(APIC_SELF_IPI, vector);
 }
 
-static void send_ipi_dest(unsigned int cpu, unsigned int vector)
+static void send_ipi_dest(unsigned int cpu, unsigned int vector, bool nmi)
 {
-       update_vector(cpu, APIC_IRR, vector, true);
+       if (nmi)
+               apic_set_reg(per_cpu_ptr(savic_page, cpu), SAVIC_NMI_REQ, 1);
+       else
+               update_vector(cpu, APIC_IRR, vector, true);
 }
 
-static void send_ipi_allbut(unsigned int vector)
+static void send_ipi_allbut(unsigned int vector, bool nmi)
 {
        unsigned int cpu, src_cpu;
 
@@ -149,14 +152,17 @@ static void send_ipi_allbut(unsigned int vector)
        for_each_cpu(cpu, cpu_online_mask) {
                if (cpu == src_cpu)
                        continue;
-               send_ipi_dest(cpu, vector);
+               send_ipi_dest(cpu, vector, nmi);
        }
 }
 
-static inline void self_ipi(unsigned int vector)
+static inline void self_ipi(unsigned int vector, bool nmi)
 {
        u32 icr_low = APIC_SELF_IPI | vector;
 
+       if (nmi)
+               icr_low |= APIC_DM_NMI;
+
        native_x2apic_icr_write(icr_low, 0);
 }
 
@@ -164,22 +170,24 @@ static void savic_icr_write(u32 icr_low, u32 icr_high)
 {
        unsigned int dsh, vector;
        u64 icr_data;
+       bool nmi;
 
        dsh = icr_low & APIC_DEST_ALLBUT;
        vector = icr_low & APIC_VECTOR_MASK;
+       nmi = ((icr_low & APIC_DM_FIXED_MASK) == APIC_DM_NMI);
 
        switch (dsh) {
        case APIC_DEST_SELF:
-               self_ipi(vector);
+               self_ipi(vector, nmi);
                break;
        case APIC_DEST_ALLINC:
-               self_ipi(vector);
+               self_ipi(vector, nmi);
                fallthrough;
        case APIC_DEST_ALLBUT:
-               send_ipi_allbut(vector);
+               send_ipi_allbut(vector, nmi);
                break;
        default:
-               send_ipi_dest(icr_high, vector);
+               send_ipi_dest(icr_high, vector, nmi);
                break;
        }