Commit 5ccc2bfa authored by Waiman Long's avatar Waiman Long Committed by Jia, Yingbao
Browse files

intel_idle: Fix false positive RCU splats due to incorrect hardirqs state

mainline inclusion
from mainline-v6.0
commit d295ad34
category: feature
bugzilla: https://gitee.com/openeuler/intel-kernel/issues/IB1H2A
CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=d295ad34f236c3518634fb6403d4c0160456e470



-------------------------------------------------

Intel-SIG: commit d295ad34 intel_idle: Fix false positive RCU splats
due to incorrect hardirqs state
Backport for GNR intel_idle support and fix on 5.10

Commit 32d4fd57 ("cpuidle,intel_idle: Fix CPUIDLE_FLAG_IRQ_ENABLE")
uses raw_local_irq_enable/local_irq_disable() around call to
__intel_idle() in intel_idle_irq().

With interrupt enabled, timer tick interrupt can happen and a
subsequently call to __do_softirq() may change the lockdep hardirqs state
of a debug kernel back to 'on'. This will result in a mismatch between
the cpu hardirqs state (off) and the lockdep hardirqs state (on) causing
a number of false positive "WARNING: suspicious RCU usage" splats.

Fix that by using local_irq_disable() to disable interrupt in
intel_idle_irq().

Fixes: 32d4fd57 ("cpuidle,intel_idle: Fix CPUIDLE_FLAG_IRQ_ENABLE")
Signed-off-by: default avatarWaiman Long <longman@redhat.com>
Cc: 5.16+ <stable@vger.kernel.org> # 5.16+
Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
[ yingbao jia: amend commit log ]
Signed-off-by: default avataryingbao jia <yingbao.jia@intel.com>
parent e2b75ea5
Loading
Loading
Loading
Loading
+7 −1
Original line number Diff line number Diff line
@@ -167,7 +167,13 @@ static __cpuidle int intel_idle_irq(struct cpuidle_device *dev,
	int ret;
	raw_local_irq_enable();
	ret = __intel_idle(dev, drv, index);
	raw_local_irq_disable();

	/*
	 * The lockdep hardirqs state may be changed to 'on' with timer
	 * tick interrupt followed by __do_softirq(). Use local_irq_disable()
	 * to keep the hardirqs state correct.
	 */
	local_irq_disable();

	return ret;
}