Received: by 2002:a25:ef43:0:0:0:0:0 with SMTP id w3csp605408ybm; Wed, 27 May 2020 03:36:11 -0700 (PDT) X-Google-Smtp-Source: ABdhPJzPUOL9m06vECXZaG1SDYiEdBf34PRwZyWxsTqJ2xKnMLDf2xW7rLvlVjpAyem4RIwRBfv/ X-Received: by 2002:a17:906:3095:: with SMTP id 21mr5430795ejv.32.1590575771747; Wed, 27 May 2020 03:36:11 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1590575771; cv=none; d=google.com; s=arc-20160816; b=CN90ts5VS9VA67aPNya22gn7nkxBDT5i+M1UIP4ErdndN0LXH5iEfBx9/OuuATG2my 8y304RL4K1WrZ737M7P70i1u+4GvOK1HGPT3GoWibgR/vEw160ZTaSZvKiL37FEQGpt4 imKkw7UL/7nqdM/weXxmdZ6m53iWPhYVrvC/N5puBuYAl7s0NVNFpUu7exJI1KX+7YIo yy1BPXkkVx/XB71J/JcltLQtCH2d4lu39Mdtmi7bEh1ht1D6S7yq+cOXB1ym/RatN/2J GHo9q1NOwAlsQ9ru/yQ098W9N9oRtnbZ55B7rvJpTmViejsp5Ybq2LzxKJSxRoWRKLfm KDvg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding :robot-unsubscribe:robot-id:message-id:mime-version:references :in-reply-to:cc:subject:to:reply-to:from:date; bh=mqmJj0UXf4b0R0gus2OIxhlkH4zE1MFdPCLAl14Z2Cc=; b=Q+RzqLeyZbtcEhNH8XkrI/ZX8KD2j3l09/XunVXQ58c8Qic6p7hfyK5rM1LYobF6S0 0MVKTUK6LpZ/L83rMhbk1lYfpxIVjYORWRBt5A4MNbgiJxYPX5WFwwKW8z92FiG9FBLW yykntVd/AvE2Tm9DlTdwwm5WmFvDph5hzN1toZqpB7xhV3rIC6FupYeSCuPGObKlcdAh CBqDbKeAZB/32AnokDLPPGTVu1fa8/s9BsnUwwxOAtktdV+rQXet/oAJJnHp42T20bPY r/BSL3WPQFtIPzPAexvfU6JxDh+SaKSA+fwgV9L6OhqopblTWdplEUZ8DTG0Mne5ZQFO C0KA== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id e13si1645149ejb.684.2020.05.27.03.35.48; Wed, 27 May 2020 03:36:11 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387873AbgE0INI (ORCPT + 99 others); Wed, 27 May 2020 04:13:08 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:42250 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729541AbgE0IME (ORCPT ); Wed, 27 May 2020 04:12:04 -0400 Received: from Galois.linutronix.de (Galois.linutronix.de [IPv6:2a0a:51c0:0:12e:550::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id EBE94C03E97A; Wed, 27 May 2020 01:12:03 -0700 (PDT) Received: from [5.158.153.53] (helo=tip-bot2.lab.linutronix.de) by Galois.linutronix.de with esmtpsa (TLS1.2:DHE_RSA_AES_256_CBC_SHA256:256) (Exim 4.80) (envelope-from ) id 1jdrAP-0002dU-UY; Wed, 27 May 2020 10:12:02 +0200 Received: from [127.0.1.1] (localhost [IPv6:::1]) by tip-bot2.lab.linutronix.de (Postfix) with ESMTP id D52E41C04D6; Wed, 27 May 2020 10:11:57 +0200 (CEST) Date: Wed, 27 May 2020 08:11:57 -0000 From: "tip-bot2 for Thomas Gleixner" Reply-to: linux-kernel@vger.kernel.org To: linux-tip-commits@vger.kernel.org Subject: [tip: x86/entry] x86/entry: Provide helpers for executing on the irqstack Cc: Thomas Gleixner , Ingo Molnar , Andy Lutomirski , x86 , LKML In-Reply-To: <20200521202117.763775313@linutronix.de> References: <20200521202117.763775313@linutronix.de> MIME-Version: 1.0 Message-ID: <159056711769.17951.7240676234405001898.tip-bot2@tip-bot2> X-Mailer: tip-git-log-daemon Robot-ID: Robot-Unsubscribe: Contact to get blacklisted from these emails Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit 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 The following commit has been merged into the x86/entry branch of tip: Commit-ID: 0aa4dbb2808991f53396df8d2deb390d4f880abb Gitweb: https://git.kernel.org/tip/0aa4dbb2808991f53396df8d2deb390d4f880abb Author: Thomas Gleixner AuthorDate: Thu, 21 May 2020 22:05:23 +02:00 Committer: Ingo Molnar CommitterDate: Tue, 26 May 2020 19:06:27 +02:00 x86/entry: Provide helpers for executing on the irqstack Device interrupt handlers and system vector handlers are executed on the interrupt stack. The stack switch happens in the low level assembly entry code. This conflicts with the efforts to consolidate the exit code in C to ensure correctness vs. RCU and tracing. As there is no way to move #DB away from IST due to the MOV SS issue, the requirements vs. #DB and NMI for switching to the interrupt stack do not exist anymore. The only requirement is that interrupts are disabled. That allows the moving of the stack switching to C code, which simplifies the entry/exit handling further, because it allows the switching of stacks after handling the entry and on exit before handling RCU, returning to usermode and kernel preemption in the same way as for regular exceptions. The initial attempt of having the stack switching in inline ASM caused too much headache vs. objtool and the unwinder. After analysing the use cases it was agreed on that having the stack switch in ASM for the price of an indirect call is acceptable, as the main users are indirect call heavy anyway and the few system vectors which are empty shells (scheduler IPI and KVM posted interrupt vectors) can run from the regular stack. Provide helper functions to check whether the interrupt stack is already active and whether stack switching is required. 64-bit only for now, as 32-bit has a variant of that already. Once this is cleaned up, the two implementations might be consolidated as an additional cleanup on top. Signed-off-by: Thomas Gleixner Signed-off-by: Ingo Molnar Acked-by: Andy Lutomirski Link: https://lore.kernel.org/r/20200521202117.763775313@linutronix.de --- arch/x86/entry/entry_64.S | 39 +++++++++++++++++++++++- arch/x86/include/asm/irq_stack.h | 53 +++++++++++++++++++++++++++++++- 2 files changed, 92 insertions(+) create mode 100644 arch/x86/include/asm/irq_stack.h diff --git a/arch/x86/entry/entry_64.S b/arch/x86/entry/entry_64.S index d983a0d..1597370 100644 --- a/arch/x86/entry/entry_64.S +++ b/arch/x86/entry/entry_64.S @@ -1106,6 +1106,45 @@ SYM_CODE_START_LOCAL_NOALIGN(.Lbad_gs) SYM_CODE_END(.Lbad_gs) .previous +/* + * rdi: New stack pointer points to the top word of the stack + * rsi: Function pointer + * rdx: Function argument (can be NULL if none) + */ +SYM_FUNC_START(asm_call_on_stack) + /* + * Save the frame pointer unconditionally. This allows the ORC + * unwinder to handle the stack switch. + */ + pushq %rbp + mov %rsp, %rbp + + /* + * The unwinder relies on the word at the top of the new stack + * page linking back to the previous RSP. + */ + mov %rsp, (%rdi) + mov %rdi, %rsp + /* Move the argument to the right place */ + mov %rdx, %rdi + +1: + .pushsection .discard.instr_begin + .long 1b - . + .popsection + + CALL_NOSPEC rsi + +2: + .pushsection .discard.instr_end + .long 2b - . + .popsection + + /* Restore the previous stack pointer from RBP. */ + leaveq + ret +SYM_FUNC_END(asm_call_on_stack) + /* Call softirq on interrupt stack. Interrupts are off. */ .pushsection .text, "ax" SYM_FUNC_START(do_softirq_own_stack) diff --git a/arch/x86/include/asm/irq_stack.h b/arch/x86/include/asm/irq_stack.h new file mode 100644 index 0000000..4ae66f0 --- /dev/null +++ b/arch/x86/include/asm/irq_stack.h @@ -0,0 +1,53 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _ASM_X86_IRQ_STACK_H +#define _ASM_X86_IRQ_STACK_H + +#include + +#include + +#ifdef CONFIG_X86_64 +static __always_inline bool irqstack_active(void) +{ + return __this_cpu_read(irq_count) != -1; +} + +void asm_call_on_stack(void *sp, void *func, void *arg); + +static __always_inline void __run_on_irqstack(void *func, void *arg) +{ + void *tos = __this_cpu_read(hardirq_stack_ptr); + + __this_cpu_add(irq_count, 1); + asm_call_on_stack(tos - 8, func, arg); + __this_cpu_sub(irq_count, 1); +} + +#else /* CONFIG_X86_64 */ +static inline bool irqstack_active(void) { return false; } +static inline void __run_on_irqstack(void *func, void *arg) { } +#endif /* !CONFIG_X86_64 */ + +static __always_inline bool irq_needs_irq_stack(struct pt_regs *regs) +{ + if (IS_ENABLED(CONFIG_X86_32)) + return false; + if (!regs) + return !irqstack_active(); + return !user_mode(regs) && !irqstack_active(); +} + +static __always_inline void run_on_irqstack_cond(void *func, void *arg, + struct pt_regs *regs) +{ + void (*__func)(void *arg) = func; + + lockdep_assert_irqs_disabled(); + + if (irq_needs_irq_stack(regs)) + __run_on_irqstack(__func, arg); + else + __func(arg); +} + +#endif