History

entry/kvm: Explicitly flush pending rcuog wakeup before last rescheduling point

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.

Frederic Weisbecker committed 5 years ago

Commit 4ae7dc91 parent 47b8ff14 files · +50 −10Browse files

Showing the changes to kernel (2 of 4 files). Show all

Unified · Split

2 files
  1. kernel/rcu/tree.c +34 −10
  2. kernel/rcu/tree_plugin.h +1 −0
kernel/rcu/tree.c+34−10
@@ -678,9 +678,10 @@ EXPORT_SYMBOL_GPL(rcu_idle_enter); · 677 unmodified lines
678678
679679 #ifdef CONFIG_NO_HZ_FULL
680680
681+#if !defined(CONFIG_GENERIC_ENTRY) || !defined(CONFIG_KVM_XFER_TO_GUEST_WORK)
681682 /*
682683 * An empty function that will trigger a reschedule on
683− * IRQ tail once IRQs get re-enabled on userspace resume.
684+ * IRQ tail once IRQs get re-enabled on userspace/guest resume.
684685 */
685686 static void late_wakeup_func(struct irq_work *work)
686687 {
@@ -689,6 +690,37 @@ static void late_wakeup_func(struct irq_work *work) · 2 unmodified lines
689690 static DEFINE_PER_CPU(struct irq_work, late_wakeup_work) =
690691 IRQ_WORK_INIT(late_wakeup_func);
691692
693+/*
694+ * If either:
695+ *
696+ * 1) the task is about to enter in guest mode and $ARCH doesn't support KVM generic work
697+ * 2) the task is about to enter in user mode and $ARCH doesn't support generic entry.
698+ *
699+ * In these cases the late RCU wake ups aren't supported in the resched loops and our
700+ * last resort is to fire a local irq_work that will trigger a reschedule once IRQs
701+ * get re-enabled again.
702+ */
703+noinstr static void rcu_irq_work_resched(void)
704+{
705+ struct rcu_data *rdp = this_cpu_ptr(&rcu_data);
706+
707+ if (IS_ENABLED(CONFIG_GENERIC_ENTRY) && !(current->flags & PF_VCPU))
708+ return;
709+
710+ if (IS_ENABLED(CONFIG_KVM_XFER_TO_GUEST_WORK) && (current->flags & PF_VCPU))
711+ return;
712+
713+ instrumentation_begin();
714+ if (do_nocb_deferred_wakeup(rdp) && need_resched()) {
715+ irq_work_queue(this_cpu_ptr(&late_wakeup_work));
716+ }
717+ instrumentation_end();
718+}
719+
720+#else
721+static inline void rcu_irq_work_resched(void) { }
722+#endif
723+
692724 /**
693725 * rcu_user_enter - inform RCU that we are resuming userspace.
694726 *
@@ -702,8 +734,6 @@ static DEFINE_PER_CPU(struct irq_work, late_wakeup_work) = · 7 unmodified lines
702734 */
703735 noinstr void rcu_user_enter(void)
704736 {
705− struct rcu_data *rdp = this_cpu_ptr(&rcu_data);
706−
707737 lockdep_assert_irqs_disabled();
708738
709739 /*
@@ -711,13 +741,7 @@ noinstr void rcu_user_enter(void) · 1 unmodified line
711741 * rescheduling opportunity in the entry code. Trigger a self IPI
712742 * that will fire and reschedule once we resume in user/guest mode.
713743 */
714− instrumentation_begin();
715− if (!IS_ENABLED(CONFIG_GENERIC_ENTRY) || (current->flags & PF_VCPU)) {
716− if (do_nocb_deferred_wakeup(rdp) && need_resched())
717− irq_work_queue(this_cpu_ptr(&late_wakeup_work));
718− }
719− instrumentation_end();
720−
744+ rcu_irq_work_resched();
721745 rcu_eqs_enter(true);
722746 }
723747
kernel/rcu/tree_plugin.h+1−0
@@ -2197,6 +2197,7 @@ void rcu_nocb_flush_deferred_wakeup(void) · 2196 unmodified lines
21972197 {
21982198 do_nocb_deferred_wakeup(this_cpu_ptr(&rcu_data));
21992199 }
2200+EXPORT_SYMBOL_GPL(rcu_nocb_flush_deferred_wakeup);
22002201
22012202 void __init rcu_init_nohz(void)
22022203 {

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t