Re: [PATCH] PM: hibernate: flush icache for restored pages from task context

Xiong Xin <[email protected]>
Newsgroups org.kernel.vger.linux-pm
Message-ID <[email protected]>
> On Mon, Aug 03, 2026 at 01:54:12PM +0800, Xiong Xin wrote:
>> When resuming from hibernation with `hibernate=nocompress`, the kernel
>> loads the image via load_image(), which submits read bios asynchronously
>> and waits on them with hib_wait_io(). The bio completion callback
>> hib_end_io() runs from the block IRQ/softirq path.
>>
>> Commit f6cf0545ec69 ("PM / Hibernate: Call flush_icache_range() on pages
>> restored in-place") added a flush_icache_range() call inside hib_end_io()
>> (under clean_pages_on_read). On architectures such as ARM64,
>> flush_icache_range() ends with kick_all_cpus_sync() -> smp_call_function()
>> (wait=1), which contains:
>>
>>      WARN_ON_ONCE(!in_task());
>>
>> Because hib_end_io() executes in hardirq/softirq context, in_task() is
>> always false there, and the WARN fires which happens while the resume
>> task is asleep in hib_wait_io() and the CPU is idle, the warning log as
>> follows:
> 
> Hmm, do we have any secondary CPUs online at this point? I wonder if
> either smp_call_function() could push the WARN() down into the branch
> where it knows it is going to call remotely or whether we could elide
> the call to kick_all_cpus_sync() altogether in that case?

Thanks for the review.

Q1: Do we have any secondary CPUs online at this point?

Yes, the secondary CPUs are online, but they are all (almost) in the idle
loop state. The current problem is that the CPU enters idle state due 
toio wait and there are no other processes that can be scheduled (All 
userprocesses and most kernel threads have been frozen). Then it is 
awakenedby an interrupt (irq) to handle the asynchronous IO callback 
function
hib_end_io(). As a result, the kick_all_cpus_sync() call is triggered
in the interrupt context, leading to the generation of a WARNING message.
Is this unrelated to whether other CPUs are online?

Q: Could we elide kick_all_cpus_sync() when all other CPUs are idle?

That's a good suggestion.

But as far as I know, the idle check cannot be made race-free. idle_cpu()
or available_idle_cpu() is a best-effort snapshot. There is a TOCTOU window
between the check and the elision during which another CPU can be woken by
any interrupt and start executing the flushed range with stale I-cache 
entries.

So, in the flush_icache_range() function, is it safe to check whether all
other CPUs are in the idle state?
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.