Received: by 2002:a25:f815:0:0:0:0:0 with SMTP id u21csp2488436ybd; Mon, 24 Jun 2019 07:18:05 -0700 (PDT) X-Google-Smtp-Source: APXvYqyF/xk3JkJF9r8drpYP8m08rYO7LqbWqvSus1BSAdLUsBrMGnLegX1nPnMWVza5ZjnDUalu X-Received: by 2002:a63:8b4c:: with SMTP id j73mr22911509pge.11.1561385885561; Mon, 24 Jun 2019 07:18:05 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1561385885; cv=none; d=google.com; s=arc-20160816; b=MoUTHugjjcOWDwj/8vIeV3fBqf9MLoOS5oFlYfYVZyTF8U1SS42lZCgvAjCQSaO/9u grkH3ZMJT4ZtW9vK79ZVEzLDa29Z+ITDgC3vLBiMYunePUBeM6MunF0WmgT0ZJbQ/WcV l995t/G12vXKT79Q0qSOrQe5lPU7iIrXHEZA+oabRCCAUR0marNVAVwJLYicEx+vFkCe fweOTIlbv7YTYGsd++GyA+YD2vEvCBjUNrTUAXN/JSBwfZ7LI5aGq11okjAqoTk/pJZY jU1cT4rgkF4VSco0SHqeiy3/Bb2kplUbZuiSeYkjrGKAtVSqgCp8PjUbLGaS69YeqtV/ 328w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:mime-version:user-agent:references :message-id:in-reply-to:subject:cc:to:from:date; bh=BeGHJ9/4xVjSLl5rE/fF9n+aIKTDJiBzjVGHLTEz8pM=; b=wqV6E7lZYcVAlraMFmuyKbninXs6Di0zCmkIYYu0TnNj4ZXAH+8AnwjXnNPzZloS1Q e2AqvhyLevHSa2rPuDT85x9R9XexGaXsLBObB5ZepW9rqDjRcTkNJlt+2cstJ6sqDQkX dKkhNYnICmZkytDnhdBQEKqjxeXghED8MrllfttvuDBYj9XQgE+td5I0wf49BNVOp8hW E0DEIULypCGOMu52GKmlCSCgzQoQrG6pEEVZ4ipxCqlHoxHyhaTJt9yV8/cBqUE8HJ1F 4ZYOCxCj9kCTLgk7zyCn0B2DRJaM3LZrYKOVBxusPpziekRH0EQdD6E8jXBc/w3Tzg2d RGMA== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id 14si11196808pfz.120.2019.06.24.07.17.49; Mon, 24 Jun 2019 07:18:05 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1731299AbfFXNrI (ORCPT + 99 others); Mon, 24 Jun 2019 09:47:08 -0400 Received: from Galois.linutronix.de ([193.142.43.55]:36910 "EHLO Galois.linutronix.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729954AbfFXNrH (ORCPT ); Mon, 24 Jun 2019 09:47:07 -0400 Received: from p5b06daab.dip0.t-ipconnect.de ([91.6.218.171] helo=nanos) by Galois.linutronix.de with esmtpsa (TLS1.2:DHE_RSA_AES_256_CBC_SHA256:256) (Exim 4.80) (envelope-from ) id 1hfPIq-0003An-PU; Mon, 24 Jun 2019 15:46:36 +0200 Date: Mon, 24 Jun 2019 15:46:36 +0200 (CEST) From: Thomas Gleixner To: Jan Kiszka cc: Ingo Molnar , Borislav Petkov , x86@kernel.org, Linux Kernel Mailing List , Jan Beulich Subject: Re: x86: Spurious vectors not handled robustly In-Reply-To: Message-ID: References: <1565f016-4e3b-fa89-62e5-fc77594ee5aa@siemens.com> User-Agent: Alpine 2.21 (DEB 202 2017-01-01) MIME-Version: 1.0 Content-Type: text/plain; charset=US-ASCII X-Linutronix-Spam-Score: -1.0 X-Linutronix-Spam-Level: - X-Linutronix-Spam-Status: No , -1.0 points, 5.0 required, ALL_TRUSTED=-1,SHORTCIRCUIT=-0.0001 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Mon, 24 Jun 2019, Thomas Gleixner wrote: > On Mon, 24 Jun 2019, Jan Kiszka wrote: > > On 24.06.19 12:09, Thomas Gleixner wrote: > > > 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. > > Bah. Of course I did not look at that ... > > /me goes back to stare at the code. The patch below should fix it. It's quick tested on 64bit (without inducing a spurious vector) and compile tested on 32bit. Can you please give it a try with your failure case? Thanks, tglx 8<---------------- Subject: x86/irq: Seperate unused system vectors from spurious entry again From: Thomas Gleixner Date: Mon, 24 Jun 2019 13:34:06 +0200 Quite some time ago the interrupt entry stubs for unused vectors in the system vector range got removed and directly mapped to the spurious interrupt vector entry point. Sounds reasonable, but it's subtly broken. The spurious interrupt vector entry point pushes vector number 0xFF on the stack which makes the whole logic in smp_spurious_interrupt() pointless. As a consequence any spurious interrupt which comes from a vector != 0xFF is treated as a real spurious interrupt (vector 0xFF) and not acknowledged. That subsequently stalls all interrupt vectors of equal and lower priority, which brings the system to a grinding halt. This can happen because even on 64-bit the system vector space is not guaranteed to be fully populated. A full compile time handling of the unused vectors is not possible because quite some of them are conditonally populated at runtime. Bring the entry stubs back, which wastes 160 bytes if all stubs are unused, but gains the proper handling back. There is no point to selectively spare some of the stubs which are known at compile time as the required code in the IDT management would be way larger and convoluted. The array is straight forward and simple. Do not route the spurious entries through common_interrupt and do_IRQ() as the original code did. Route it to smp_spurious_interrupt() which evaluates the vector number and acts accordingly now that the real vector numbers are handed in. Fixes: 2414e021ac8d ("x86: Avoid building unused IRQ entry stubs") Reported-by: Jan Kiszka Signed-off-by: Thomas Gleixner Cc: Jan Beulich --- arch/x86/entry/entry_32.S | 24 ++++++++++++++++++++++++ arch/x86/entry/entry_64.S | 30 ++++++++++++++++++++++++++---- arch/x86/include/asm/hw_irq.h | 2 ++ arch/x86/kernel/idt.c | 3 ++- 4 files changed, 54 insertions(+), 5 deletions(-) --- a/arch/x86/entry/entry_32.S +++ b/arch/x86/entry/entry_32.S @@ -1104,6 +1104,30 @@ ENTRY(irq_entries_start) .endr END(irq_entries_start) +#ifdef CONFIG_X86_LOCAL_APIC + .align 8 +ENTRY(spurious_entries_start) + vector=FIRST_SYSTEM_VECTOR + .rept (NR_VECTORS - FIRST_SYSTEM_VECTOR) + pushl $(~vector+0x80) /* Note: always in signed byte range */ + vector=vector+1 + jmp common_spurious_vector + .align 8 + .endr +END(spurious_entries_start) + +common_spurious: + ASM_CLAC + addl $-0x80, (%esp) /* Adjust vector into the [-256, -1] range */ + SAVE_ALL switch_stacks=1 + ENCODE_FRAME_POINTER + TRACE_IRQS_OFF + movl %esp, %eax + call smp_spurious_interrupt + jmp ret_from_intr +ENDPROC(common_interrupt) +#endif + /* * the CPU automatically disables interrupts when executing an IRQ vector, * so IRQ-flags tracing has to follow that: --- a/arch/x86/entry/entry_64.S +++ b/arch/x86/entry/entry_64.S @@ -375,6 +375,18 @@ ENTRY(irq_entries_start) .endr END(irq_entries_start) + .align 8 +ENTRY(spurious_entries_start) + vector=FIRST_SYSTEM_VECTOR + .rept (NR_VECTORS - FIRST_SYSTEM_VECTOR) + UNWIND_HINT_IRET_REGS + pushq $(~vector+0x80) /* Note: always in signed byte range */ + jmp common_spurious + .align 8 + vector=vector+1 + .endr +END(spurious_entries_start) + .macro DEBUG_ENTRY_ASSERT_IRQS_OFF #ifdef CONFIG_DEBUG_ENTRY pushq %rax @@ -571,10 +583,20 @@ END(interrupt_entry) /* Interrupt entry/exit. */ - /* - * The interrupt stubs push (~vector+0x80) onto the stack and - * then jump to common_interrupt. - */ +/* + * The interrupt stubs push (~vector+0x80) onto the stack and + * then jump to common_spurious/interrupt. + */ +common_spurious: + addq $-0x80, (%rsp) /* Adjust vector to [-256, -1] range */ + call interrupt_entry + UNWIND_HINT_REGS indirect=1 + call smp_spurious_interrupt /* rdi points to pt_regs */ + jmp ret_from_intr +END(common_spurious) +_ASM_NOKPROBE(common_spurious) + +/* common_interrupt is a hotpath. Align it */ .p2align CONFIG_X86_L1_CACHE_SHIFT common_interrupt: addq $-0x80, (%rsp) /* Adjust vector to [-256, -1] range */ --- a/arch/x86/include/asm/hw_irq.h +++ b/arch/x86/include/asm/hw_irq.h @@ -150,6 +150,8 @@ extern char irq_entries_start[]; #define trace_irq_entries_start irq_entries_start #endif +extern char spurious_entries_start[]; + #define VECTOR_UNUSED NULL #define VECTOR_RETRIGGERED ((void *)~0UL) --- a/arch/x86/kernel/idt.c +++ b/arch/x86/kernel/idt.c @@ -319,7 +319,8 @@ void __init idt_setup_apic_and_irq_gates #ifdef CONFIG_X86_LOCAL_APIC for_each_clear_bit_from(i, system_vectors, NR_VECTORS) { set_bit(i, system_vectors); - set_intr_gate(i, spurious_interrupt); + entry = spurious_entries_start + 8 * (i - FIRST_SYSTEM_VECTOR); + set_intr_gate(i, entry); } #endif }