linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Thomas Gleixner <tglx@linutronix.de>
To: LKML <linux-kernel@vger.kernel.org>
Cc: x86@kernel.org, linux-arch@vger.kernel.org,
	Will Deacon <will@kernel.org>, Arnd Bergmann <arnd@arndb.de>,
	Mark Rutland <mark.rutland@arm.com>,
	Kees Cook <keescook@chromium.org>,
	Keno Fischer <keno@juliacomputing.com>,
	Paolo Bonzini <pbonzini@redhat.com>,
	kvm@vger.kernel.org,
	Gabriel Krisman Bertazi <krisman@collabora.com>
Subject: [patch V4 05/15] entry: Provide infrastructure for work before exiting to guest mode
Date: Tue, 21 Jul 2020 12:57:11 +0200	[thread overview]
Message-ID: <20200721110808.780082657@linutronix.de> (raw)
In-Reply-To: 20200721105706.030914876@linutronix.de

From: Thomas Gleixner <tglx@linutronix.de>

Entering a guest is similar to exiting to user space. Pending work like
handling signals, rescheduling, task work etc. needs to be handled before
that.

Provide generic infrastructure to avoid duplication of the same handling
code all over the place.

The exit to guest mode handling is different from the exit to usermode
handling, e.g. vs. rseq and live patching, so a separate function is used.

The initial list of work items handled is:

    TIF_SIGPENDING, TIF_NEED_RESCHED, TIF_NOTIFY_RESUME

Architecture specific TIF flags can be added via defines in the
architecture specific include files.

The calling convention is also different from the syscall/interrupt entry
functions as KVM invokes this from the outer vcpu_run() loop with
interrupts and preemption disabled. To prevent missing a pending work item
it invokes a check for pending TIF work from interrupt disabled code right
before exiting to guest mode. The lockdep, RCU and tracing state handling
is also done directly around the switch to and from guest mode.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
V3: Reworked and simplified version adopted to recent X86 and KVM changes
    
V2: Moved KVM specific functions to kvm (Paolo)
    Added lockdep assert (Andy)
    Dropped live patching from enter guest mode work (Miroslav)
---
 include/linux/entry-kvm.h |   80 ++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/kvm_host.h  |    8 ++++
 kernel/entry/Makefile     |    3 +
 kernel/entry/kvm.c        |   51 +++++++++++++++++++++++++++++
 virt/kvm/Kconfig          |    3 +
 5 files changed, 144 insertions(+), 1 deletion(-)

--- /dev/null
+++ b/include/linux/entry-kvm.h
@@ -0,0 +1,80 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __LINUX_ENTRYKVM_H
+#define __LINUX_ENTRYKVM_H
+
+#include <linux/entry-common.h>
+
+/* Exit to guest mode work */
+#ifdef CONFIG_KVM_EXIT_TO_GUEST_WORK
+
+#ifndef ARCH_EXIT_TO_GUEST_MODE_WORK
+# define ARCH_EXIT_TO_GUEST_MODE_WORK	(0)
+#endif
+
+#define EXIT_TO_GUEST_MODE_WORK					\
+	(_TIF_NEED_RESCHED | _TIF_SIGPENDING |			\
+	 _TIF_NOTIFY_RESUME | ARCH_EXIT_TO_GUEST_MODE_WORK)
+
+struct kvm_vcpu;
+
+/**
+ * arch_exit_to_guest_mode_work - Architecture specific exit to guest mode
+ *				  work function.
+ * @vcpu:	Pointer to current's VCPU data
+ * @ti_work:	Cached TIF flags gathered in exit_to_guest_mode()
+ *
+ * Invoked from exit_to_guest_mode_work(). Defaults to NOOP. Can be
+ * replaced by architecture specific code.
+ */
+static inline int arch_exit_to_guest_mode_work(struct kvm_vcpu *vcpu,
+					      unsigned long ti_work);
+
+#ifndef arch_exit_to_guest_mode_work
+static inline int arch_exit_to_guest_mode_work(struct kvm_vcpu *vcpu,
+					       unsigned long ti_work)
+{
+	return 0;
+}
+#endif
+
+/**
+ * exit_to_guest_mode - Check and handle pending work which needs to be
+ *			handled before returning to guest mode
+ * @vcpu:	Pointer to current's VCPU data
+ *
+ * Returns: 0 or an error code
+ */
+int exit_to_guest_mode(struct kvm_vcpu *vcpu);
+
+/**
+ * __exit_to_guest_mode_work_pending - Check if work is pending
+ *
+ * Returns: True if work pending, False otherwise.
+ *
+ * Bare variant of exit_to_guest_mode_work_pending(). Can be called from
+ * interrupt enabled code for racy quick checks with care.
+ */
+static inline bool __exit_to_guest_mode_work_pending(void)
+{
+	unsigned long ti_work = READ_ONCE(current_thread_info()->flags);
+
+	return !!(ti_work & EXIT_TO_GUEST_MODE_WORK);
+}
+
+/**
+ * exit_to_guest_mode_work_pending - Check if work is pending which needs to be
+ *				     handled before returning to guest mode
+ *
+ * Returns: True if work pending, False otherwise.
+ *
+ * Has to be invoked with interrupts disabled before the transition to
+ * guest mode.
+ */
+static inline bool exit_to_guest_mode_work_pending(void)
+{
+	lockdep_assert_irqs_disabled();
+	return __exit_to_guest_mode_work_pending();
+}
+#endif /* CONFIG_KVM_EXIT_TO_GUEST_WORK */
+
+#endif

--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -1439,4 +1439,12 @@ int kvm_vm_create_worker_thread(struct k
 				uintptr_t data, const char *name,
 				struct task_struct **thread_ptr);
 
+#ifdef CONFIG_KVM_EXIT_TO_GUEST_WORK
+static inline void kvm_handle_signal_exit(struct kvm_vcpu *vcpu)
+{
+	vcpu->run->exit_reason = KVM_EXIT_INTR;
+	vcpu->stat.signal_exits++;
+}
+#endif /* CONFIG_KVM_EXIT_TO_GUEST_WORK */
+
 #endif
--- a/kernel/entry/Makefile
+++ b/kernel/entry/Makefile
@@ -1,3 +1,4 @@
 # SPDX-License-Identifier: GPL-2.0
 
-obj-$(CONFIG_GENERIC_ENTRY) += common.o
+obj-$(CONFIG_GENERIC_ENTRY) 		+= common.o
+obj-$(CONFIG_KVM_EXIT_TO_GUEST_WORK)	+= kvm.o
--- /dev/null
+++ b/kernel/entry/kvm.c
@@ -0,0 +1,51 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/entry-kvm.h>
+#include <linux/kvm_host.h>
+
+static int exit_to_guest_mode_work(struct kvm_vcpu *vcpu, unsigned long ti_work)
+{
+	do {
+		int ret;
+
+		if (ti_work & _TIF_SIGPENDING) {
+			kvm_handle_signal_exit(vcpu);
+			return -EINTR;
+		}
+
+		if (ti_work & _TIF_NEED_RESCHED)
+			schedule();
+
+		if (ti_work & _TIF_NOTIFY_RESUME) {
+			clear_thread_flag(TIF_NOTIFY_RESUME);
+			tracehook_notify_resume(NULL);
+		}
+
+		ret = arch_exit_to_guest_mode_work(vcpu, ti_work);
+		if (ret)
+			return ret;
+
+		ti_work = READ_ONCE(current_thread_info()->flags);
+	} while (ti_work & EXIT_TO_GUEST_MODE_WORK || need_resched());
+	return 0;
+}
+
+int exit_to_guest_mode(struct kvm_vcpu *vcpu)
+{
+	unsigned long ti_work;
+
+	/*
+	 * This is invoked from the outer guest loop with interrupts and
+	 * preemption enabled.
+	 *
+	 * KVM invokes exit_to_guest_mode_work_pending() with interrupts
+	 * disabled in the inner loop before going into guest mode. No need
+	 * to disable interrupts here.
+	 */
+	ti_work = READ_ONCE(current_thread_info()->flags);
+	if (!(ti_work & EXIT_TO_GUEST_MODE_WORK))
+		return 0;
+
+	return exit_to_guest_mode_work(vcpu, ti_work);
+}
+EXPORT_SYMBOL_GPL(exit_to_guest_mode);
--- a/virt/kvm/Kconfig
+++ b/virt/kvm/Kconfig
@@ -60,3 +60,6 @@ config HAVE_KVM_VCPU_RUN_PID_CHANGE
 
 config HAVE_KVM_NO_POLL
        bool
+
+config KVM_EXIT_TO_GUEST_WORK
+       bool



  parent reply	other threads:[~2020-07-21 11:10 UTC|newest]

Thread overview: 31+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-07-21 10:57 [patch V4 00/15] entry, x86, kvm: Generic entry/exit functionality for host and guest Thomas Gleixner
2020-07-21 10:57 ` [patch V4 01/15] seccomp: Provide stub for __secure_computing() Thomas Gleixner
2020-07-21 21:21   ` Kees Cook
2020-07-21 10:57 ` [patch V4 02/15] entry: Provide generic syscall entry functionality Thomas Gleixner
2020-07-21 21:38   ` Kees Cook
2020-07-22  7:34     ` Thomas Gleixner
2020-07-22  7:54     ` peterz
2020-07-21 10:57 ` [patch V4 03/15] entry: Provide generic syscall exit function Thomas Gleixner
2020-07-27 22:37   ` Andy Lutomirski
2020-07-21 10:57 ` [patch V4 04/15] entry: Provide generic interrupt entry/exit code Thomas Gleixner
2020-07-27 22:39   ` Andy Lutomirski
2020-07-29 12:18     ` Thomas Gleixner
2020-07-21 10:57 ` Thomas Gleixner [this message]
2020-07-21 10:57 ` [patch V4 06/15] x86/entry: Consolidate check_user_regs() Thomas Gleixner
2020-07-27 22:39   ` Andy Lutomirski
2020-07-21 10:57 ` [patch V4 07/15] x86/entry: Consolidate 32/64 bit syscall entry Thomas Gleixner
2020-07-21 10:57 ` [patch V4 08/15] x86/entry: Move user return notifier out of loop Thomas Gleixner
2020-07-21 10:57 ` [patch V4 09/15] x86/ptrace: Provide pt_regs helper for entry/exit Thomas Gleixner
2020-07-21 10:57 ` [patch V4 10/15] x86/entry: Use generic syscall entry function Thomas Gleixner
2020-07-21 21:47   ` Kees Cook
2020-07-22 18:25     ` Thomas Gleixner
2020-07-21 10:57 ` [patch V4 11/15] x86/entry: Use generic syscall exit functionality Thomas Gleixner
2020-07-21 21:47   ` Kees Cook
2020-07-21 10:57 ` [patch V4 12/15] x86/entry: Cleanup idtentry_entry/exit_user Thomas Gleixner
2020-07-21 21:48   ` Kees Cook
2020-07-21 10:57 ` [patch V4 13/15] x86/entry: Use generic interrupt entry/exit code Thomas Gleixner
2020-07-21 10:57 ` [patch V4 14/15] x86/entry: Cleanup idtentry_enter/exit Thomas Gleixner
2020-07-21 21:48   ` Kees Cook
2020-07-21 10:57 ` [patch V4 15/15] x86/kvm: Use generic exit to guest work function Thomas Gleixner
2020-07-21 20:27   ` Sean Christopherson
2020-07-22  7:40     ` Thomas Gleixner

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200721110808.780082657@linutronix.de \
    --to=tglx@linutronix.de \
    --cc=arnd@arndb.de \
    --cc=keescook@chromium.org \
    --cc=keno@juliacomputing.com \
    --cc=krisman@collabora.com \
    --cc=kvm@vger.kernel.org \
    --cc=linux-arch@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mark.rutland@arm.com \
    --cc=pbonzini@redhat.com \
    --cc=will@kernel.org \
    --cc=x86@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).