[linux-pm] [RFC PATCH v4] ARM hibernation/suspend-to-disk support
Frank Hofmann
frank.hofmann at tomtom.com
Fri Jun 10 10:54:05 EDT 2011
On Fri, 10 Jun 2011, Russell King - ARM Linux wrote:
>> [ ... ]
> I think there's a fundamental problem here - what's required for S2RAM
> is not what's required for hibernate. After cpu_suspend() has done
> its job, you are in a _very_ specific environment designed for the last
> stages of S2RAM _only_ and not hibernate.
>
> In order to use cpu_suspend() for hibernate, it requires a completely
> different path entirely, and there's no getting away from that.
>
> You can see that when you analyze the differences between S2RAM and
> hibernate, when you realize that the final part of the S2RAM process
> (which happens after cpu_suspend() returns) on many SoCs is dealing
> with putting SDRAM into self-refresh mode before writing some kind of
> power mode register to tell the power supply to kill power to most
> of the platform. That is all _very_ SoC specific.
Yes, that's what I'm trying to say - the _final_ stage, for s2ram, sends
the SoC to low-power.
Up until there, we do the same for hibernation, don't we ? Where exactly
is it different ?
>
> Also realize that the code which executes after cpu_suspend() returns
> is _not_ running in the same context as the code which called
> cpu_suspend() - cpu_suspend() has modified the stack pointer to store
> the CPU specific state and that is not the same stack pointer as was
> the case before cpu_suspend() was called.
Yes, the function isn't "well behaved" from the ABI point of view because
it doesn't preserve registers (including the stack), but that can be
accommodated by the caller.
The current s2ram callers have to accommodate that as well. Which is
ultimately easy for them - since poweroff doesn't care.
The only reason why hibernation / swsusp_arch_suspend() is different there
is because the activity _after_ cpu_suspend() is extensive and _can fail_
(saving the image); on that failure, one would prefer to see an error
message and continue instead of panicing the system. So the stack change
you mention needs to be addressed, swsusp_arch_suspend() must be a
well-behaved function from the ABI point of view.
Normally, if all goes _right_, swsusp_save() does not return either. It
ends powering the system off. If one were willing to die without message
on failure to save the snapshot to disk, and would be willing to block
cpu_suspend during writing the snapshot (to guarantee sleep_save_sp isn't
changing) one wouldn't need to care about the stack and could simply:
ENTRY(swsusp_arch_suspend)
mrs r1, cpsr
mrs r2, spsr
stmfd sp! {r1-r12,lr}
bl __swsusp_arch_get_vpoffset
mov r1, r0
adr r3, .Lresume_post_mmu
bl cpu_suspend
bl swsusp_save
0:
b 0b @ should never reach this
ENDPROC(swsusp_arch_suspend)
Resume is quite trivial either way:
ENTRY(swsusp_arch_resume)
setmode PSR_I_BIT | PSR_F_BIT | SVC_MODE, r2
ldr sp, =(__swsusp_resume_stk + PAGE_SIZE / 2)
/*
* replays image, and ends in cpu_reset(cpu_resume)
*/
b __swsusp_arch_restore_image
.Lresume_post_mmu:
ldmfd sp!, {r1-r12}
msr cpsr, r1
msr spsr, r2
bl cpu_init @ reinitialize other modes
ldmfd sp!, {lr}
b __swsusp_arch_resume_finish @ cleanup
ENDPROC(swsusp_arch_resume)
>
> You don't want to run any of that code when you're dealing with hibernate,
> so expecting to be able to reuse these S2RAM paths is not realistic.
Hmm, well ... in the end, hibernation does:
<snapshot state>
<some long operation that writes the image out>
<poweroff>
while s2ram does:
<snapshot state>
<some quick operation setting low power modes>
<poweroff>
>
> What we could do is provide a cpu_hibernate() function which has saner
> semantics for saving the CPU specific state for hibernate.
Yes, that's exactly what I'm hoping for. From my point of view, this
would, though, end up in:
cpu_soc_suspend:
cpu_hibernate_snapshot_state();
/* S2RAM codepath to send soc to low power */
cpu_soc_resume:
/* S2RAM codepath for waking up soc essentials */
cpu_hibernate_restore_state();
At least I can't come up with a really good reason why the state
snapshotting operation would have to be different between s2ram and
s2disk.
FrankH.
More information about the linux-arm-kernel
mailing list