Received: by 2002:a05:6a10:9848:0:0:0:0 with SMTP id x8csp3405992pxf; Mon, 22 Mar 2021 05:51:26 -0700 (PDT) X-Google-Smtp-Source: ABdhPJwK1iQOv/6zMFRsKIeqMtwUd/HLHqblc9LHfCnfLNHmkGbJMOefCq1ZmumUix1kL4MM3hjd X-Received: by 2002:a17:906:1a16:: with SMTP id i22mr19422834ejf.522.1616417485982; Mon, 22 Mar 2021 05:51:25 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1616417485; cv=none; d=google.com; s=arc-20160816; b=AscL5y9QgBsWS+CmwSm/JiRZWHSKHzTGBpMdDqI/S4hv0P1EG8tVwrxscWXEtFe49m EUaiuKHAHUhe4wCobbuYesGrbFWl5VmoW/M96kARIFqVzKCdKHknguudEpGxHUdsWQza Ytpb3eYkfzO8Si2MszhFITCEffVJReF6DpGISuigGksWmL8QOUEtOuj3EZYJyj54BQ+o z+L9WyV2GL1lfjnkriUvVUdm1MYlZczQMXcLsZepTGriXcioxcDL9/luoVqxToSXwB+j TJj2yj6bhS9Z7AyUcsuPuML/UTY0o+HiY+jgSYhk629UxWYFsUDc56KPYxCw3D4Tyo9W /8fQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=dlrmCIuBtauT9uPh3fpO02YFJthi0y1JFqiz3QCXrs0=; b=egKt8bjrQRRJW3kkAm+KHCGDYEJMsOnzl9cKPI8fp6KNuhA2Rvqvjqa9CUdSpBSeP7 +lEO1EYK54lxsy4kD67kCEk4MWfbUjahiBCoK1upuGyYisSJEC9zAEPVXnR10hDfCXsd OEVJNA+KAI/ww0MY/URkcOU19X/V1nAOqMrW2I7BUmhNXfYeDM3mG4otdWqvS0XsYxj2 M6pwYtGfz02E/75pkpM/fChz568yJ00tXu81atXgitKi50VWl6732RTtSZsc1/y5kMad Y/C/MZCGuz704nMaLfRmWzwLbqiECaA2S16LdpZltfzP6r0dU0zXEOz7WnDl4wg0PV/E nJ6Q== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=eORnT6z+; 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; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id y3si11228082edo.515.2021.03.22.05.51.01; Mon, 22 Mar 2021 05:51:25 -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; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=eORnT6z+; 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; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232845AbhCVMsT (ORCPT + 99 others); Mon, 22 Mar 2021 08:48:19 -0400 Received: from mail.kernel.org ([198.145.29.99]:35514 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232048AbhCVMjp (ORCPT ); Mon, 22 Mar 2021 08:39:45 -0400 Received: by mail.kernel.org (Postfix) with ESMTPSA id EB313619A9; Mon, 22 Mar 2021 12:38:38 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1616416719; bh=vDeGE7Yyd0mUQ4b2mNnmpqLMLCF2zUHF2mHfSWUKaCA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=eORnT6z+LXx8kYTcRiUbNsUJZmY7OUuz9+ULct853H56NeuRXHosknAI6Sbl4NT/s IduiLpXM0PP0HvKKnrSsFv1Q6zcatfwOXhL5IkWWygWIDUsl8PPR9sXzeQpE1+KE9h eUCpxT93NuPpWfYEI/Ud7FNYyCUToKvYtIaWRvuY= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Peter Zijlstra , Frederic Weisbecker , Ingo Molnar , Sasha Levin Subject: [PATCH 5.10 094/157] entry/kvm: Explicitly flush pending rcuog wakeup before last rescheduling point Date: Mon, 22 Mar 2021 13:27:31 +0100 Message-Id: <20210322121936.759526540@linuxfoundation.org> X-Mailer: git-send-email 2.31.0 In-Reply-To: <20210322121933.746237845@linuxfoundation.org> References: <20210322121933.746237845@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Frederic Weisbecker [ Upstream commit 4ae7dc97f726ea95c58ac58af71cc034ad22d7de ] Following the idle loop model, cleanly check for pending rcuog wakeup before the last rescheduling point upon resuming to guest mode. This way we can avoid to do it from rcu_user_enter() with the last resort self-IPI hack that enforces rescheduling. Suggested-by: Peter Zijlstra Signed-off-by: Frederic Weisbecker Signed-off-by: Peter Zijlstra (Intel) Signed-off-by: Ingo Molnar Cc: stable@vger.kernel.org Link: https://lkml.kernel.org/r/20210131230548.32970-6-frederic@kernel.org Signed-off-by: Sasha Levin --- arch/x86/kvm/x86.c | 1 + include/linux/entry-kvm.h | 14 +++++++++++++ kernel/rcu/tree.c | 44 ++++++++++++++++++++++++++++++--------- kernel/rcu/tree_plugin.h | 1 + 4 files changed, 50 insertions(+), 10 deletions(-) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index fa5f059c2b94..08bb14e3bd61 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -1776,6 +1776,7 @@ EXPORT_SYMBOL_GPL(kvm_emulate_wrmsr); bool kvm_vcpu_exit_request(struct kvm_vcpu *vcpu) { + xfer_to_guest_mode_prepare(); return vcpu->mode == EXITING_GUEST_MODE || kvm_request_pending(vcpu) || xfer_to_guest_mode_work_pending(); } diff --git a/include/linux/entry-kvm.h b/include/linux/entry-kvm.h index 0cef17afb41a..d60ab08f9058 100644 --- a/include/linux/entry-kvm.h +++ b/include/linux/entry-kvm.h @@ -46,6 +46,20 @@ static inline int arch_xfer_to_guest_mode_handle_work(struct kvm_vcpu *vcpu, */ int xfer_to_guest_mode_handle_work(struct kvm_vcpu *vcpu); +/** + * xfer_to_guest_mode_prepare - Perform last minute preparation work that + * need to be handled while IRQs are disabled + * upon entering to guest. + * + * Has to be invoked with interrupts disabled before the last call + * to xfer_to_guest_mode_work_pending(). + */ +static inline void xfer_to_guest_mode_prepare(void) +{ + lockdep_assert_irqs_disabled(); + rcu_nocb_flush_deferred_wakeup(); +} + /** * __xfer_to_guest_mode_work_pending - Check if work is pending * diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c index 0d8a2e2df221..eff2f7359a4c 100644 --- a/kernel/rcu/tree.c +++ b/kernel/rcu/tree.c @@ -670,9 +670,10 @@ EXPORT_SYMBOL_GPL(rcu_idle_enter); #ifdef CONFIG_NO_HZ_FULL +#if !defined(CONFIG_GENERIC_ENTRY) || !defined(CONFIG_KVM_XFER_TO_GUEST_WORK) /* * An empty function that will trigger a reschedule on - * IRQ tail once IRQs get re-enabled on userspace resume. + * IRQ tail once IRQs get re-enabled on userspace/guest resume. */ static void late_wakeup_func(struct irq_work *work) { @@ -681,6 +682,37 @@ static void late_wakeup_func(struct irq_work *work) static DEFINE_PER_CPU(struct irq_work, late_wakeup_work) = IRQ_WORK_INIT(late_wakeup_func); +/* + * If either: + * + * 1) the task is about to enter in guest mode and $ARCH doesn't support KVM generic work + * 2) the task is about to enter in user mode and $ARCH doesn't support generic entry. + * + * In these cases the late RCU wake ups aren't supported in the resched loops and our + * last resort is to fire a local irq_work that will trigger a reschedule once IRQs + * get re-enabled again. + */ +noinstr static void rcu_irq_work_resched(void) +{ + struct rcu_data *rdp = this_cpu_ptr(&rcu_data); + + if (IS_ENABLED(CONFIG_GENERIC_ENTRY) && !(current->flags & PF_VCPU)) + return; + + if (IS_ENABLED(CONFIG_KVM_XFER_TO_GUEST_WORK) && (current->flags & PF_VCPU)) + return; + + instrumentation_begin(); + if (do_nocb_deferred_wakeup(rdp) && need_resched()) { + irq_work_queue(this_cpu_ptr(&late_wakeup_work)); + } + instrumentation_end(); +} + +#else +static inline void rcu_irq_work_resched(void) { } +#endif + /** * rcu_user_enter - inform RCU that we are resuming userspace. * @@ -694,8 +726,6 @@ static DEFINE_PER_CPU(struct irq_work, late_wakeup_work) = */ noinstr void rcu_user_enter(void) { - struct rcu_data *rdp = this_cpu_ptr(&rcu_data); - lockdep_assert_irqs_disabled(); /* @@ -703,13 +733,7 @@ noinstr void rcu_user_enter(void) * rescheduling opportunity in the entry code. Trigger a self IPI * that will fire and reschedule once we resume in user/guest mode. */ - instrumentation_begin(); - if (!IS_ENABLED(CONFIG_GENERIC_ENTRY) || (current->flags & PF_VCPU)) { - if (do_nocb_deferred_wakeup(rdp) && need_resched()) - irq_work_queue(this_cpu_ptr(&late_wakeup_work)); - } - instrumentation_end(); - + rcu_irq_work_resched(); rcu_eqs_enter(true); } diff --git a/kernel/rcu/tree_plugin.h b/kernel/rcu/tree_plugin.h index 29a00d9ea286..a9351906e290 100644 --- a/kernel/rcu/tree_plugin.h +++ b/kernel/rcu/tree_plugin.h @@ -2197,6 +2197,7 @@ void rcu_nocb_flush_deferred_wakeup(void) { do_nocb_deferred_wakeup(this_cpu_ptr(&rcu_data)); } +EXPORT_SYMBOL_GPL(rcu_nocb_flush_deferred_wakeup); void __init rcu_init_nohz(void) { -- 2.30.1