diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2024-01-08 17:45:24 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2024-01-08 17:45:24 -0800 |
commit | 33677aef32cf07ebbed07647e88136258c4b95ba (patch) | |
tree | 587c47b4ccc74fb6a8dfd60122bbcfcc2488fafd /arch/x86 | |
parent | b51cc5d02834a9c38cfd95b00b7d981b701b13f9 (diff) | |
parent | edc8fc01f608108b0b7580cb2c29dfb5135e5f0e (diff) |
Merge tag 'x86-core-2024-01-08' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 core updates from Ingo Molnar:
- Add comments about the magic behind the shadow STI
before MWAIT in __sti_mwait().
- Fix possible unintended timer delays caused by a race
in mwait_idle_with_hints().
* tag 'x86-core-2024-01-08' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
x86: Fix CPUIDLE_FLAG_IRQ_ENABLE leaking timer reprogram
x86: Add a comment about the "magic" behind shadow sti before mwait
Diffstat (limited to 'arch/x86')
-rw-r--r-- | arch/x86/include/asm/mwait.h | 20 |
1 files changed, 18 insertions, 2 deletions
diff --git a/arch/x86/include/asm/mwait.h b/arch/x86/include/asm/mwait.h index 778df05f8539..920426d691ce 100644 --- a/arch/x86/include/asm/mwait.h +++ b/arch/x86/include/asm/mwait.h @@ -87,6 +87,15 @@ static __always_inline void __mwaitx(unsigned long eax, unsigned long ebx, :: "a" (eax), "b" (ebx), "c" (ecx)); } +/* + * Re-enable interrupts right upon calling mwait in such a way that + * no interrupt can fire _before_ the execution of mwait, ie: no + * instruction must be placed between "sti" and "mwait". + * + * This is necessary because if an interrupt queues a timer before + * executing mwait, it would otherwise go unnoticed and the next tick + * would not be reprogrammed accordingly before mwait ever wakes up. + */ static __always_inline void __sti_mwait(unsigned long eax, unsigned long ecx) { mds_idle_clear_cpu_buffers(); @@ -115,8 +124,15 @@ static __always_inline void mwait_idle_with_hints(unsigned long eax, unsigned lo } __monitor((void *)¤t_thread_info()->flags, 0, 0); - if (!need_resched()) - __mwait(eax, ecx); + + if (!need_resched()) { + if (ecx & 1) { + __mwait(eax, ecx); + } else { + __sti_mwait(eax, ecx); + raw_local_irq_disable(); + } + } } current_clr_polling(); } |