Skip to content

Commit ce0a928

Browse files
Jacob PanKAGA-KOKO
authored andcommitted
x86/irq: Extend checks for pending vectors to posted interrupts
During interrupt affinity change, it is possible to have interrupts delivered to the old CPU after the affinity has changed to the new one. To prevent lost interrupts, local APIC IRR is checked on the old CPU. Similar checks must be done for posted MSIs given the same reason. Consider the following scenario: Device system agent iommu memory CPU/LAPIC 1 FEEX_XXXX 2 Interrupt request 3 Fetch IRTE -> 4 ->Atomic Swap PID.PIR(vec) Push to Global Observable(GO) 5 if (ON*) done;* else 6 send a notification -> * ON: outstanding notification, 1 will suppress new notifications If the affinity change happens between 3 and 5 in the IOMMU, the old CPU's posted interrupt request (PIR) could have the pending bit set for the vector being moved. Add a helper function to check individual vector status. Then use the helper to check for pending interrupts on the source CPU's PID. Signed-off-by: Jacob Pan <[email protected]> Signed-off-by: Thomas Gleixner <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent fef05a0 commit ce0a928

File tree

2 files changed

+20
-1
lines changed

2 files changed

+20
-1
lines changed

arch/x86/include/asm/apic.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include <asm/msr.h>
1515
#include <asm/hardirq.h>
1616
#include <asm/io.h>
17+
#include <asm/posted_intr.h>
1718

1819
#define ARCH_APICTIMER_STOPS_ON_C3 1
1920

@@ -508,7 +509,7 @@ static inline bool is_vector_pending(unsigned int vector)
508509
if (irr & (1 << (vector % 32)))
509510
return true;
510511

511-
return false;
512+
return pi_pending_this_cpu(vector);
512513
}
513514

514515
/*

arch/x86/include/asm/posted_intr.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/* SPDX-License-Identifier: GPL-2.0 */
22
#ifndef _X86_POSTED_INTR_H
33
#define _X86_POSTED_INTR_H
4+
#include <asm/irq_vectors.h>
45

56
#define POSTED_INTR_ON 0
67
#define POSTED_INTR_SN 1
@@ -92,8 +93,25 @@ static inline void __pi_clear_sn(struct pi_desc *pi_desc)
9293
}
9394

9495
#ifdef CONFIG_X86_POSTED_MSI
96+
/*
97+
* Not all external vectors are subject to interrupt remapping, e.g. IOMMU's
98+
* own interrupts. Here we do not distinguish them since those vector bits in
99+
* PIR will always be zero.
100+
*/
101+
static inline bool pi_pending_this_cpu(unsigned int vector)
102+
{
103+
struct pi_desc *pid = this_cpu_ptr(&posted_msi_pi_desc);
104+
105+
if (WARN_ON_ONCE(vector > NR_VECTORS || vector < FIRST_EXTERNAL_VECTOR))
106+
return false;
107+
108+
return test_bit(vector, (unsigned long *)pid->pir);
109+
}
110+
95111
extern void intel_posted_msi_init(void);
96112
#else
113+
static inline bool pi_pending_this_cpu(unsigned int vector) { return false; }
114+
97115
static inline void intel_posted_msi_init(void) {};
98116
#endif /* X86_POSTED_MSI */
99117

0 commit comments

Comments
 (0)