diff options
-rw-r--r-- | arch/x86/kernel/apic/x2apic_savic.c | 26 |
1 files changed, 17 insertions, 9 deletions
diff --git a/arch/x86/kernel/apic/x2apic_savic.c b/arch/x86/kernel/apic/x2apic_savic.c index bdefe4cd4e29..8ed56e87c32f 100644 --- a/arch/x86/kernel/apic/x2apic_savic.c +++ b/arch/x86/kernel/apic/x2apic_savic.c @@ -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; } |