Re: x86: Spurious vectors not handled robustly

From: Jan Kiszka
Date: Mon Jun 24 2019 - 06:39:09 EST


On 24.06.19 12:09, Thomas Gleixner wrote:
Jan,

On Mon, 24 Jun 2019, Jan Kiszka wrote:
probably since "x86: Avoid building unused IRQ entry stubs" (2414e021ac8d),
the kernel can no longer tell spurious IRQs by the APIC apart from spuriously
triggered unused vectors.

Err. It does.

We've managed to trigger such a cause with the Jailhouse hypervisor
(incorrectly injected MANAGED_IRQ_SHUTDOWN_VECTOR), and the result was
not only a misreport of the vector number (0xff instead of 0xef - took me
a while...), but also stalled interrupts of equal and lower priority
because a spurious interrupt is not (and must not be) acknowledged.

That does not make sense.

__visible void __irq_entry smp_spurious_interrupt(struct pt_regs *regs)
{
u8 vector = ~regs->orig_ax;
u32 v;

entering_irq();
trace_spurious_apic_entry(vector);
/*
* Check if this really is a spurious interrupt and ACK it
* if it is a vectored one. Just in case...
*/
v = apic_read(APIC_ISR + ((vector & ~0x1f) >> 1));
if (v & (1 << (vector & 0x1f)))
ack_APIC_irq();

If it is a vectored one it _IS_ acked.

inc_irq_stat(irq_spurious_count);

/* see sw-dev-man vol 3, chapter 7.4.13.5 */
pr_info("spurious APIC interrupt through vector %02x on CPU#%d, "
"should never happen.\n", vector, smp_processor_id());

and the vector through which that comes is printed correctly, unless
regs->orig_ax is hosed.

...which is exactly the case: Since that commit, all unused vectors share the same entry point, spurious_interrupt, see idt_setup_apic_and_irq_gates(). And that entry point sets orig_ax to ~0xff.

Jan

--
Siemens AG, Corporate Technology, CT RDA IOT SES-DE
Corporate Competence Center Embedded Linux