* [RFC PATCH v5] ARM hibernation / suspend-to-disk (fwd)
@ 2011-06-13 12:04 Frank Hofmann
2011-06-13 12:26 ` Russell King - ARM Linux
2011-09-30 7:48 ` Barry Song
0 siblings, 2 replies; 21+ messages in thread
From: Frank Hofmann @ 2011-06-13 12:04 UTC (permalink / raw)
To: linux-arm-kernel
Hi,
to make one thing clear to start with:
This is not a proposal to integrate the hibernation feature into mainline.
It's not ripe for that because it's unclear what exactly the differences are
between what the hibernation / S2RAM codepaths have to do, and/or how much code
sharing between these codepaths is advisable.
Therefore, I'm merely putting this out as-is as a reference / base for those
who want to do their own experiments with the feature.
Prerequisites:
* The patch requires a working cpu_reset(); for v6/v7, that's in Will
Deacon's patch series from last week.
* It also requires being able to take the address of cpu_reset and
on MULTI_CPU configs therefore, again see Will Deacon's patch series.
* It uses on cpu_suspend() / cpu_resume(), therefore a recent-enough
kernel (or a port of those to whatever you're using) is required.
Important / Limitations:
A) For platforms that currently use cpu_suspend/cpu_resume in their s2ram
codepaths AND DO NOTHING ELSE BEFORE AND NOTHING ELSE AFTER THAT BUT TO
"ENTER LOW POWER", the way the hibernation state snapshot for the CPU
core is done by this patch is sufficient.
To make it clear: IF AND ONLY IF your suspend(-to-ram) func looks like:
ENTRY(acmeSoC_cpu_suspend)
stmfd sp!, {r4-r12,lr}
ldr r3, resume_mmu_done
bl cpu_suspend
resume_mmu_done:
ldmfd sp!, {r3-r12,pc}
ENDPROC(acmeSoC_cpu_suspend)
then this patch is ok to provide hibernation support for your CPU core.
In all other cases, item B).
IN ALL CASES, read item C) below; there's more than the core to the SoC.
B) If there's any cpu-specific / SoC-specific state that needs (re)init
over a suspend-to-disk/resume-from-disk cycle, this patch is incomplete
because it provides no hooks/code for that.
This is the case e.g. for "secure" SoCs that have different sets of
control registers and/or different CR reg access patterns.
It's also the case e.g. for SoCs with L2 caches as the activation
sequence there is SoC-dependent; a full off-on cycle for L2 is not done
by the hibernation support code.
It's also the case if the SoC requires steps on wakeup _before_ the
"generic" parts done by cpu_suspend / cpu_resume can work correctly.
(OMAP is an example of such a SoC; the patch "works" on OMAP in the
sense that it gets you a non-secure OMAP back from hibernation but as
mentioned, your mileage may vary; I for example don't know what the
consequences of not disabling / reenabling the L2 cache over cpu_reset
are)
C) The current low-power handling may perform SoC-specific tasks such
as GPIO state handling, which is currently also not addressed by this
patch; the assumption is rather that device suspend/resume deals with
this. That is not guaranteed to be complete / sufficient - if your SoC
and/or your device drivers have particular needs in this area, you can
put hooks performing these actions into save_/restore_processor_state().
D) If you wish to extend this to a SoC for which the generic CPU core
hooks (i.e. what cpu_suspend/resume provide) are either insufficient
or unavailable, hook your own state snapshot mechanism into the places
where this code currently calls cpu_suspend and cpu_resume. The main
assumption by the assembly code within swusp_arch_resume() is that
__swsusp_arch_restore_image() returns to its caller with the stack
restored - how you achieve that is up to you, the patch as-is does it
by cpu_reset(cpu_resume) but your mileage may vary.
I will, at this point, not send further iterations of this patch.
I'll answer questions about it though, if there are any.
Thanks for all the comments during the previous threads - learned a lot !
Best regards,
FrankH.
^ permalink raw reply [flat|nested] 21+ messages in thread
* [RFC PATCH v5] ARM hibernation / suspend-to-disk (fwd)
2011-06-13 12:04 [RFC PATCH v5] ARM hibernation / suspend-to-disk (fwd) Frank Hofmann
@ 2011-06-13 12:26 ` Russell King - ARM Linux
2011-06-13 12:40 ` Frank Hofmann
2011-06-13 13:20 ` Frank Hofmann
2011-09-30 7:48 ` Barry Song
1 sibling, 2 replies; 21+ messages in thread
From: Russell King - ARM Linux @ 2011-06-13 12:26 UTC (permalink / raw)
To: linux-arm-kernel
On Mon, Jun 13, 2011 at 01:04:02PM +0100, Frank Hofmann wrote:
> To make it clear: IF AND ONLY IF your suspend(-to-ram) func looks like:
>
> ENTRY(acmeSoC_cpu_suspend)
> stmfd sp!, {r4-r12,lr}
> ldr r3, resume_mmu_done
> bl cpu_suspend
> resume_mmu_done:
> ldmfd sp!, {r3-r12,pc}
> ENDPROC(acmeSoC_cpu_suspend)
Nothing has that - because you can't execute that ldmfd after the call
to cpu_suspend returns. I don't think you've understood what I said on
that subject in the previous thread.
^ permalink raw reply [flat|nested] 21+ messages in thread
* [RFC PATCH v5] ARM hibernation / suspend-to-disk (fwd)
2011-06-13 12:26 ` Russell King - ARM Linux
@ 2011-06-13 12:40 ` Frank Hofmann
2011-06-13 13:20 ` Frank Hofmann
1 sibling, 0 replies; 21+ messages in thread
From: Frank Hofmann @ 2011-06-13 12:40 UTC (permalink / raw)
To: linux-arm-kernel
On Mon, 13 Jun 2011, Russell King - ARM Linux wrote:
> On Mon, Jun 13, 2011 at 01:04:02PM +0100, Frank Hofmann wrote:
>> To make it clear: IF AND ONLY IF your suspend(-to-ram) func looks like:
>>
>> ENTRY(acmeSoC_cpu_suspend)
>> stmfd sp!, {r4-r12,lr}
>> ldr r3, resume_mmu_done
>> bl cpu_suspend
>> resume_mmu_done:
>> ldmfd sp!, {r3-r12,pc}
>> ENDPROC(acmeSoC_cpu_suspend)
>
> Nothing has that - because you can't execute that ldmfd after the call
> to cpu_suspend returns. I don't think you've understood what I said on
> that subject in the previous thread.
>
Sorry typo.
Missed the critical lines:
ENTRY(acmeSoC_cpu_suspend)
stmfd sp!, {r3-r12,lr}
ldr r3, =resume_mmu_done
[ load r1 with v:p, whichever way - either you or your caller ]
bl cpu_suspend
[ ... do whatever low power entry stuff ... ]
[ function effectively ENDS HERE ... ]
resume_mmu_done:
ldmfd sp!, {r3-r12,pc}
That's the key bits. DO NOTHING OF RELEVANCE BEFORE cpu_suspend AND DO
NOTHING APART FROM ENTERING LOW POWER AFTERWARDS.
I _have_ understood what you've said. cpu_suspend is not made for this
purpose, and hence I'm not claiming it should be. The use of it to create
the core state snapshot for hibernation is merely something that, right
now, works _by accident_ (or sheer luck, if you want to say that) rather
than by intent / design.
Since there _is no design_ for what should work / how it should work in
this context, I'm leaving it as-is, merely stating the constraints. Roll
your own if you need / want to.
Does that clarify ?
FrankH.
^ permalink raw reply [flat|nested] 21+ messages in thread
* [RFC PATCH v5] ARM hibernation / suspend-to-disk (fwd)
2011-06-13 12:26 ` Russell King - ARM Linux
2011-06-13 12:40 ` Frank Hofmann
@ 2011-06-13 13:20 ` Frank Hofmann
2011-06-13 13:56 ` Dave Martin
2011-06-13 16:44 ` Russell King - ARM Linux
1 sibling, 2 replies; 21+ messages in thread
From: Frank Hofmann @ 2011-06-13 13:20 UTC (permalink / raw)
To: linux-arm-kernel
On Mon, 13 Jun 2011, Russell King - ARM Linux wrote:
> On Mon, Jun 13, 2011 at 01:04:02PM +0100, Frank Hofmann wrote:
>> To make it clear: IF AND ONLY IF your suspend(-to-ram) func looks like:
>>
>> ENTRY(acmeSoC_cpu_suspend)
>> stmfd sp!, {r4-r12,lr}
>> ldr r3, resume_mmu_done
>> bl cpu_suspend
>> resume_mmu_done:
>> ldmfd sp!, {r3-r12,pc}
>> ENDPROC(acmeSoC_cpu_suspend)
>
> Nothing has that - because you can't execute that ldmfd after the call
> to cpu_suspend returns. I don't think you've understood what I said on
> that subject in the previous thread.
>
Ok, to illustrate a bit more, what is ok and what not.
>From bogus@does.not.exist.com Wed Jun 1 12:03:18 2011
From: bogus@does.not.exist.com ()
Date: Wed, 01 Jun 2011 16:03:18 -0000
Subject: No subject
Message-ID: <mailman.22.1307971213.24103.linux-arm-kernel@lists.infradead.org>
a) a case where the hibernation patch as I posted it is ok for core state:
arch/arm/mach-exynos4/sleep.S has:
ENTRY(s3c_cpu_save)
stmfd sp!, { r3 - r12, lr }
ldr r3, =resume_with_mmu
bl cpu_suspend
ldr r0, =pm_cpu_sleep
ldr r0, [ r0 ]
mov pc, r0
resume_with_mmu:
ldmfd sp!, { r3 - r12, pc }
ENTRY(s3c_cpu_resume)
b cpu_resume
I.e. it does nothing before but set up the arguments for cpu_suspend, and
does nothing afterwards but redirect to a function that enters low power
(and switches the CPU off).
Likewise, all it does for resume is redirect to cpu_resume which will
ultimately end up jumping to resume_with_mmu: as requested.
b) a case where the hibernation patch is insufficient even though the
code in the soc suspend func uses cpu_suspend:
arch/arm/mach-pxa/sleep.S has:
/*
* pxa27x_cpu_suspend()
*
* Forces CPU into sleep state.
*
* r0 = value for PWRMODE M field for desired sleep state
* r1 = v:p offset
*/
ENTRY(pxa27x_cpu_suspend)
#ifndef CONFIG_IWMMXT
mra r2, r3, acc0
#endif
stmfd sp!, {r2 - r12, lr} @ save registers on stack
mov r4, r0 @ save sleep mode
ldr r3, =pxa_cpu_resume @ resume function
bl cpu_suspend
[ ... some stuff ... ]
ldr r6, =CCCR
ldr r8, [r6] @ keep original value for resume
ldr r7, =CCCR_SLEEP @ prepare CCCR sleep value
mov r0, #0x2 @ prepare value for CLKCFG
@ align execution to a cache line
b pxa_cpu_do_suspend
#endif
[ ... ]
pxa_cpu_do_suspend:
@ All needed values are now in registers.
@ These last instructions should be in cache
@ initiate the frequency change...
str r7, [r6]
mcr p14, 0, r0, c6, c0, 0
@ restore the original cpu speed value for resume
str r8, [r6]
[ ... ]
/*
* pxa_cpu_resume()
*
* entry point from bootloader into kernel during resume
*/
.align 5
pxa_cpu_resume:
ldmfd sp!, {r2, r3}
#ifndef CONFIG_IWMMXT
mar acc0, r2, r3
#endif
ldmfd sp!, {r4 - r12, pc} @ return to caller
In this case, there's _MORE_ state saved (the CCCR / CCCR_SLEEP accesses)
after the call to cpu_suspend things that aren't dealt with by the way the
hibernation support patch currently operates.
There also is _more_ restored at resume than what the generic part does
for you.
Whether these things (for example) are relevant wrt. to a hibernation
resume is something I simply do not know.
A third example of a soc suspend func, even more complex, with more
constraints, would be as already mentioned, OMAP. On that as well the
caveat applies, "what works empirically might not be correct in all
cases".
This hopefully illustrates what someone who tries to make suspend-to-disk
work for a particular ARM SoC has to look out for, and why the patch
shouldn't be blindly adopted ?!
Again, it's only a starting point. An improved one compared to having
ARCH-#ifdefs and huge code bloat all over swsusp.S, but not sufficient for
the general case quite yet.
FrankH.
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [RFC PATCH v5] ARM hibernation / suspend-to-disk (fwd)
2011-06-13 13:20 ` Frank Hofmann
@ 2011-06-13 13:56 ` Dave Martin
2011-06-13 16:44 ` Russell King - ARM Linux
1 sibling, 0 replies; 21+ messages in thread
From: Dave Martin @ 2011-06-13 13:56 UTC (permalink / raw)
To: Santosh Shilimkar, Frank Hofmann
Cc: Russell King - ARM Linux, Colin Cross, linux-kernel, linux-arm-kernel
On Mon, Jun 13, 2011 at 02:20:12PM +0100, Frank Hofmann wrote:
>
>
> On Mon, 13 Jun 2011, Russell King - ARM Linux wrote:
>
> >On Mon, Jun 13, 2011 at 01:04:02PM +0100, Frank Hofmann wrote:
> >> To make it clear: IF AND ONLY IF your suspend(-to-ram) func looks like:
> >>
> >> ENTRY(acmeSoC_cpu_suspend)
> >> stmfd sp!, {r4-r12,lr}
> >> ldr r3, resume_mmu_done
> >> bl cpu_suspend
> >> resume_mmu_done:
> >> ldmfd sp!, {r3-r12,pc}
> >> ENDPROC(acmeSoC_cpu_suspend)
> >
> >Nothing has that - because you can't execute that ldmfd after the call
> >to cpu_suspend returns. I don't think you've understood what I said on
> >that subject in the previous thread.
> >
>
> Ok, to illustrate a bit more, what is ok and what not.
>
>
> From the current code ...
>
> a) a case where the hibernation patch as I posted it is ok for core state:
>
> arch/arm/mach-exynos4/sleep.S has:
>
> ENTRY(s3c_cpu_save)
>
> stmfd sp!, { r3 - r12, lr }
> ldr r3, =resume_with_mmu
> bl cpu_suspend
>
> ldr r0, =pm_cpu_sleep
> ldr r0, [ r0 ]
> mov pc, r0
>
> resume_with_mmu:
> ldmfd sp!, { r3 - r12, pc }
>
> ENTRY(s3c_cpu_resume)
> b cpu_resume
>
>
> I.e. it does nothing before but set up the arguments for
> cpu_suspend, and does nothing afterwards but redirect to a function
> that enters low power (and switches the CPU off).
> Likewise, all it does for resume is redirect to cpu_resume which
> will ultimately end up jumping to resume_with_mmu: as requested.
>
>
> b) a case where the hibernation patch is insufficient even though the
> code in the soc suspend func uses cpu_suspend:
>
> arch/arm/mach-pxa/sleep.S has:
>
> /*
> * pxa27x_cpu_suspend()
> *
> * Forces CPU into sleep state.
> *
> * r0 = value for PWRMODE M field for desired sleep state
> * r1 = v:p offset
> */
> ENTRY(pxa27x_cpu_suspend)
>
> #ifndef CONFIG_IWMMXT
> mra r2, r3, acc0
> #endif
> stmfd sp!, {r2 - r12, lr} @ save registers on stack
> mov r4, r0 @ save sleep mode
> ldr r3, =pxa_cpu_resume @ resume function
> bl cpu_suspend
> [ ... some stuff ... ]
> ldr r6, =CCCR
> ldr r8, [r6] @ keep original value for resume
>
> ldr r7, =CCCR_SLEEP @ prepare CCCR sleep value
> mov r0, #0x2 @ prepare value for CLKCFG
>
> @ align execution to a cache line
> b pxa_cpu_do_suspend
> #endif
> [ ... ]
> pxa_cpu_do_suspend:
>
> @ All needed values are now in registers.
> @ These last instructions should be in cache
>
> @ initiate the frequency change...
> str r7, [r6]
> mcr p14, 0, r0, c6, c0, 0
>
> @ restore the original cpu speed value for resume
> str r8, [r6]
> [ ... ]
> /*
> * pxa_cpu_resume()
> *
> * entry point from bootloader into kernel during resume
> */
> .align 5
> pxa_cpu_resume:
> ldmfd sp!, {r2, r3}
> #ifndef CONFIG_IWMMXT
> mar acc0, r2, r3
> #endif
> ldmfd sp!, {r4 - r12, pc} @ return to caller
>
>
>
> In this case, there's _MORE_ state saved (the CCCR / CCCR_SLEEP
> accesses) after the call to cpu_suspend things that aren't dealt
> with by the way the hibernation support patch currently operates.
>
> There also is _more_ restored at resume than what the generic part
> does for you.
>
> Whether these things (for example) are relevant wrt. to a
> hibernation resume is something I simply do not know.
>
>
> A third example of a soc suspend func, even more complex, with more
> constraints, would be as already mentioned, OMAP. On that as well
> the caveat applies, "what works empirically might not be correct in
> all cases".
Santosh, Frank: to what extent do you think the OMAP suspend code could
be abstracted using something like Colin's CPU pm notifier framework?
I'd hope that at least some stuff can be abstracted out, but I don't
understand the OMAP code intimately enough to be certain of that...
We shouldn't expect to remove absolutely all the SoC specifics from
suspend code, but the more we can hook into a generic framework, the
better for everyone.
Cheers
---Dave
^ permalink raw reply [flat|nested] 21+ messages in thread
* [RFC PATCH v5] ARM hibernation / suspend-to-disk (fwd)
@ 2011-06-13 13:56 ` Dave Martin
0 siblings, 0 replies; 21+ messages in thread
From: Dave Martin @ 2011-06-13 13:56 UTC (permalink / raw)
To: linux-arm-kernel
On Mon, Jun 13, 2011 at 02:20:12PM +0100, Frank Hofmann wrote:
>
>
> On Mon, 13 Jun 2011, Russell King - ARM Linux wrote:
>
> >On Mon, Jun 13, 2011 at 01:04:02PM +0100, Frank Hofmann wrote:
> >> To make it clear: IF AND ONLY IF your suspend(-to-ram) func looks like:
> >>
> >> ENTRY(acmeSoC_cpu_suspend)
> >> stmfd sp!, {r4-r12,lr}
> >> ldr r3, resume_mmu_done
> >> bl cpu_suspend
> >> resume_mmu_done:
> >> ldmfd sp!, {r3-r12,pc}
> >> ENDPROC(acmeSoC_cpu_suspend)
> >
> >Nothing has that - because you can't execute that ldmfd after the call
> >to cpu_suspend returns. I don't think you've understood what I said on
> >that subject in the previous thread.
> >
>
> Ok, to illustrate a bit more, what is ok and what not.
>
>
> From the current code ...
>
> a) a case where the hibernation patch as I posted it is ok for core state:
>
> arch/arm/mach-exynos4/sleep.S has:
>
> ENTRY(s3c_cpu_save)
>
> stmfd sp!, { r3 - r12, lr }
> ldr r3, =resume_with_mmu
> bl cpu_suspend
>
> ldr r0, =pm_cpu_sleep
> ldr r0, [ r0 ]
> mov pc, r0
>
> resume_with_mmu:
> ldmfd sp!, { r3 - r12, pc }
>
> ENTRY(s3c_cpu_resume)
> b cpu_resume
>
>
> I.e. it does nothing before but set up the arguments for
> cpu_suspend, and does nothing afterwards but redirect to a function
> that enters low power (and switches the CPU off).
> Likewise, all it does for resume is redirect to cpu_resume which
> will ultimately end up jumping to resume_with_mmu: as requested.
>
>
> b) a case where the hibernation patch is insufficient even though the
> code in the soc suspend func uses cpu_suspend:
>
> arch/arm/mach-pxa/sleep.S has:
>
> /*
> * pxa27x_cpu_suspend()
> *
> * Forces CPU into sleep state.
> *
> * r0 = value for PWRMODE M field for desired sleep state
> * r1 = v:p offset
> */
> ENTRY(pxa27x_cpu_suspend)
>
> #ifndef CONFIG_IWMMXT
> mra r2, r3, acc0
> #endif
> stmfd sp!, {r2 - r12, lr} @ save registers on stack
> mov r4, r0 @ save sleep mode
> ldr r3, =pxa_cpu_resume @ resume function
> bl cpu_suspend
> [ ... some stuff ... ]
> ldr r6, =CCCR
> ldr r8, [r6] @ keep original value for resume
>
> ldr r7, =CCCR_SLEEP @ prepare CCCR sleep value
> mov r0, #0x2 @ prepare value for CLKCFG
>
> @ align execution to a cache line
> b pxa_cpu_do_suspend
> #endif
> [ ... ]
> pxa_cpu_do_suspend:
>
> @ All needed values are now in registers.
> @ These last instructions should be in cache
>
> @ initiate the frequency change...
> str r7, [r6]
> mcr p14, 0, r0, c6, c0, 0
>
> @ restore the original cpu speed value for resume
> str r8, [r6]
> [ ... ]
> /*
> * pxa_cpu_resume()
> *
> * entry point from bootloader into kernel during resume
> */
> .align 5
> pxa_cpu_resume:
> ldmfd sp!, {r2, r3}
> #ifndef CONFIG_IWMMXT
> mar acc0, r2, r3
> #endif
> ldmfd sp!, {r4 - r12, pc} @ return to caller
>
>
>
> In this case, there's _MORE_ state saved (the CCCR / CCCR_SLEEP
> accesses) after the call to cpu_suspend things that aren't dealt
> with by the way the hibernation support patch currently operates.
>
> There also is _more_ restored at resume than what the generic part
> does for you.
>
> Whether these things (for example) are relevant wrt. to a
> hibernation resume is something I simply do not know.
>
>
> A third example of a soc suspend func, even more complex, with more
> constraints, would be as already mentioned, OMAP. On that as well
> the caveat applies, "what works empirically might not be correct in
> all cases".
Santosh, Frank: to what extent do you think the OMAP suspend code could
be abstracted using something like Colin's CPU pm notifier framework?
I'd hope that at least some stuff can be abstracted out, but I don't
understand the OMAP code intimately enough to be certain of that...
We shouldn't expect to remove absolutely all the SoC specifics from
suspend code, but the more we can hook into a generic framework, the
better for everyone.
Cheers
---Dave
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [RFC PATCH v5] ARM hibernation / suspend-to-disk (fwd)
2011-06-13 13:56 ` Dave Martin
@ 2011-06-13 15:34 ` Frank Hofmann
-1 siblings, 0 replies; 21+ messages in thread
From: Frank Hofmann @ 2011-06-13 15:34 UTC (permalink / raw)
To: Dave Martin
Cc: Santosh Shilimkar, Frank Hofmann, Russell King - ARM Linux,
Colin Cross, linux-kernel, linux-arm-kernel
On Mon, 13 Jun 2011, Dave Martin wrote:
[ ... ]
> Santosh, Frank: to what extent do you think the OMAP suspend code could
> be abstracted using something like Colin's CPU pm notifier framework?
>
> I'd hope that at least some stuff can be abstracted out, but I don't
> understand the OMAP code intimately enough to be certain of that...
>
> We shouldn't expect to remove absolutely all the SoC specifics from
> suspend code, but the more we can hook into a generic framework, the
> better for everyone.
>
> Cheers
> ---Dave
>
Hi Dave,
you mean the patch set from this weekend ?
I've still got to read through all of that in detail (currently not
getting the digest mails).
There's this thing which Russell keeps on pointing out, that a SoC is more
than a CPU core and even a CPU core is more than just the ARM itself ...
and power management somehow needs dealing with all...
To me, the picture looks a bit like:
- the "inner" thing which is the ARMv[4567] control register set
- the "semi-inner" thing which are SoC core control regs outside
of what is generic ARMv[4567], and/or which behave differently
from that due to SoC spec / errata / ...
"Secure state" probably fits amongst this as well.
- the "semi-outer" parts like optional ARM features (cache, VFP,
Neon, ...) which still have a generic spec
- the "outer" parts - builtin devices and their state, interrupt
controller, clocks and regulator stuff, ...
This is unfortunately simplified and the separations between these aren't
quite as clean.
It used to be so that as far as device drivers were dealing with
suspend/resume the latter bit was done via sysdev/syscore and anything
else delegated to a (SoC-specific) platform_suspend_ops entry.
Russell's changes for "generic CPU suspend/resume" get the innermost bits
into common code, while Colin's changes allow for more of the outer parts
within common code ?
Assuming I'm reading these things right, then the place where OMAP could
possibly use Colin's CPU PM notifier changes would be to convert some of
the code in omap_sram_idle() (the backbone for platform_suspend_ops on
OMAP) to use it.
To use the OMAP code for illustration (could've quoted other SoC code as
well, the kind of work to be done is similar but the details of what and
how it's done are very different ...):
void omap_sram_idle(void)
{
[ ... ]
omap3_per_save_context();
[ ... ]
omap3_core_save_context();
omap3_cm_save_context();
[ ... ]
omap3_intc_prepare_idle();
[ ... ]
_omap_sram_idle(omap3_arm_context, save_state);
cpu_init();
[ ... ]
omap3_core_restore_context();
omap3_cm_restore_context();
omap3_sram_restore_context();
omap2_sms_restore_context();
[ ... ]
omap3_intc_resume_idle();
[ ... ]
omap3_per_restore_context();
[ ... ]
}
Aren't things like these potential candidates to convert to Colin's
framework, if one chooses so ?
While the place where OMAP might possibly be using Russell's generic
cpu_suspend/resume were deeper down - within _omap_sram_idle. Note the _ -
it's a function pointer actually evaluating to omap????_cpu_suspend.
So it's kind of a two-pronged attack to minimize the SoC-specific code,
Colin's framework to extract common code from the "outer" parts and
Russell's cpu_suspend/resume to extract common code from the "inner"
parts.
Orthogonal problems / solutions ?
FrankH.
^ permalink raw reply [flat|nested] 21+ messages in thread
* [RFC PATCH v5] ARM hibernation / suspend-to-disk (fwd)
@ 2011-06-13 15:34 ` Frank Hofmann
0 siblings, 0 replies; 21+ messages in thread
From: Frank Hofmann @ 2011-06-13 15:34 UTC (permalink / raw)
To: linux-arm-kernel
On Mon, 13 Jun 2011, Dave Martin wrote:
[ ... ]
> Santosh, Frank: to what extent do you think the OMAP suspend code could
> be abstracted using something like Colin's CPU pm notifier framework?
>
> I'd hope that at least some stuff can be abstracted out, but I don't
> understand the OMAP code intimately enough to be certain of that...
>
> We shouldn't expect to remove absolutely all the SoC specifics from
> suspend code, but the more we can hook into a generic framework, the
> better for everyone.
>
> Cheers
> ---Dave
>
Hi Dave,
you mean the patch set from this weekend ?
I've still got to read through all of that in detail (currently not
getting the digest mails).
There's this thing which Russell keeps on pointing out, that a SoC is more
than a CPU core and even a CPU core is more than just the ARM itself ...
and power management somehow needs dealing with all...
To me, the picture looks a bit like:
- the "inner" thing which is the ARMv[4567] control register set
- the "semi-inner" thing which are SoC core control regs outside
of what is generic ARMv[4567], and/or which behave differently
from that due to SoC spec / errata / ...
"Secure state" probably fits amongst this as well.
- the "semi-outer" parts like optional ARM features (cache, VFP,
Neon, ...) which still have a generic spec
- the "outer" parts - builtin devices and their state, interrupt
controller, clocks and regulator stuff, ...
This is unfortunately simplified and the separations between these aren't
quite as clean.
It used to be so that as far as device drivers were dealing with
suspend/resume the latter bit was done via sysdev/syscore and anything
else delegated to a (SoC-specific) platform_suspend_ops entry.
Russell's changes for "generic CPU suspend/resume" get the innermost bits
into common code, while Colin's changes allow for more of the outer parts
within common code ?
Assuming I'm reading these things right, then the place where OMAP could
possibly use Colin's CPU PM notifier changes would be to convert some of
the code in omap_sram_idle() (the backbone for platform_suspend_ops on
OMAP) to use it.
To use the OMAP code for illustration (could've quoted other SoC code as
well, the kind of work to be done is similar but the details of what and
how it's done are very different ...):
void omap_sram_idle(void)
{
[ ... ]
omap3_per_save_context();
[ ... ]
omap3_core_save_context();
omap3_cm_save_context();
[ ... ]
omap3_intc_prepare_idle();
[ ... ]
_omap_sram_idle(omap3_arm_context, save_state);
cpu_init();
[ ... ]
omap3_core_restore_context();
omap3_cm_restore_context();
omap3_sram_restore_context();
omap2_sms_restore_context();
[ ... ]
omap3_intc_resume_idle();
[ ... ]
omap3_per_restore_context();
[ ... ]
}
Aren't things like these potential candidates to convert to Colin's
framework, if one chooses so ?
While the place where OMAP might possibly be using Russell's generic
cpu_suspend/resume were deeper down - within _omap_sram_idle. Note the _ -
it's a function pointer actually evaluating to omap????_cpu_suspend.
So it's kind of a two-pronged attack to minimize the SoC-specific code,
Colin's framework to extract common code from the "outer" parts and
Russell's cpu_suspend/resume to extract common code from the "inner"
parts.
Orthogonal problems / solutions ?
FrankH.
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [RFC PATCH v5] ARM hibernation / suspend-to-disk (fwd)
2011-06-13 15:34 ` Frank Hofmann
@ 2011-06-13 16:11 ` Frank Hofmann
-1 siblings, 0 replies; 21+ messages in thread
From: Frank Hofmann @ 2011-06-13 16:11 UTC (permalink / raw)
To: Frank Hofmann
Cc: Dave Martin, Santosh Shilimkar, Russell King - ARM Linux,
Colin Cross, linux-kernel, linux-arm-kernel
On Mon, 13 Jun 2011, Frank Hofmann wrote:
[ ... ]
> So it's kind of a two-pronged attack to minimize the SoC-specific code,
> Colin's framework to extract common code from the "outer" parts and Russell's
> cpu_suspend/resume to extract common code from the "inner" parts.
Also, to clarify on the hibernation side:
The biggest shortfall of the hibernation support patch that I've posted is
that it currently has no awareness of the "peripheral" side of things at
all, i.e. all the stuff done by the platform_suspend_ops->begin/enter/end
for the suspend-to-mem case isn't replicated sufficiently by the
hibernation codepath.
If you like, swsusp_arch_suspend / resume are on the same level of
complexity as are the functions in platform_suspend_ops. But the current
hibernation patch does only parts of that. It gets away with this largely
because it "resumes from ON" ...
As far as that is concerned, Russell really has a point, to do all this
properly / well for the hibernation case, a hibernation-specific approach
on the platform_ops abstraction level would be better than just to hack
low-level generics together for the sake of hacking low-level generics
together.
If just doing per-SoC hibernation, then the code bloat problem remains, on
ARM there's already platform_suspend_ops per SoC; if one adds a full set
of platform_hibernation_ops per SoC without thinking where/how to
consolidate, it'd only create another mess. Beware the beginnings ...
I had thought the idea of using cpu_suspend / resume actually made it
clear that my main point for all this "use generics wherever imaginable"
is to never allow for unnecessary bloat in the first place and hence opt
for generics even if somewhat imperfect / shoehorned for the general case.
I'd like to apologize if that didn't come over.
I'm following the work in this area; compared to where things were a year
ago a lot of things have happened already. In a way, my hope is that part
of all this blah of mine is helping to identify areas where code might be
shared even if that starts out as coincidental (as is the current use of
cpu_suspend / resume inside the hibernation patch).
FrankH.
^ permalink raw reply [flat|nested] 21+ messages in thread
* [RFC PATCH v5] ARM hibernation / suspend-to-disk (fwd)
@ 2011-06-13 16:11 ` Frank Hofmann
0 siblings, 0 replies; 21+ messages in thread
From: Frank Hofmann @ 2011-06-13 16:11 UTC (permalink / raw)
To: linux-arm-kernel
On Mon, 13 Jun 2011, Frank Hofmann wrote:
[ ... ]
> So it's kind of a two-pronged attack to minimize the SoC-specific code,
> Colin's framework to extract common code from the "outer" parts and Russell's
> cpu_suspend/resume to extract common code from the "inner" parts.
Also, to clarify on the hibernation side:
The biggest shortfall of the hibernation support patch that I've posted is
that it currently has no awareness of the "peripheral" side of things at
all, i.e. all the stuff done by the platform_suspend_ops->begin/enter/end
for the suspend-to-mem case isn't replicated sufficiently by the
hibernation codepath.
If you like, swsusp_arch_suspend / resume are on the same level of
complexity as are the functions in platform_suspend_ops. But the current
hibernation patch does only parts of that. It gets away with this largely
because it "resumes from ON" ...
As far as that is concerned, Russell really has a point, to do all this
properly / well for the hibernation case, a hibernation-specific approach
on the platform_ops abstraction level would be better than just to hack
low-level generics together for the sake of hacking low-level generics
together.
If just doing per-SoC hibernation, then the code bloat problem remains, on
ARM there's already platform_suspend_ops per SoC; if one adds a full set
of platform_hibernation_ops per SoC without thinking where/how to
consolidate, it'd only create another mess. Beware the beginnings ...
I had thought the idea of using cpu_suspend / resume actually made it
clear that my main point for all this "use generics wherever imaginable"
is to never allow for unnecessary bloat in the first place and hence opt
for generics even if somewhat imperfect / shoehorned for the general case.
I'd like to apologize if that didn't come over.
I'm following the work in this area; compared to where things were a year
ago a lot of things have happened already. In a way, my hope is that part
of all this blah of mine is helping to identify areas where code might be
shared even if that starts out as coincidental (as is the current use of
cpu_suspend / resume inside the hibernation patch).
FrankH.
^ permalink raw reply [flat|nested] 21+ messages in thread
* [RFC PATCH v5] ARM hibernation / suspend-to-disk (fwd)
2011-06-13 13:20 ` Frank Hofmann
2011-06-13 13:56 ` Dave Martin
@ 2011-06-13 16:44 ` Russell King - ARM Linux
2011-06-15 13:35 ` Frank Hofmann
1 sibling, 1 reply; 21+ messages in thread
From: Russell King - ARM Linux @ 2011-06-13 16:44 UTC (permalink / raw)
To: linux-arm-kernel
On Mon, Jun 13, 2011 at 02:20:12PM +0100, Frank Hofmann wrote:
>
>
> On Mon, 13 Jun 2011, Russell King - ARM Linux wrote:
>
>> On Mon, Jun 13, 2011 at 01:04:02PM +0100, Frank Hofmann wrote:
>>> To make it clear: IF AND ONLY IF your suspend(-to-ram) func looks like:
>>>
>>> ENTRY(acmeSoC_cpu_suspend)
>>> stmfd sp!, {r4-r12,lr}
>>> ldr r3, resume_mmu_done
>>> bl cpu_suspend
>>> resume_mmu_done:
>>> ldmfd sp!, {r3-r12,pc}
>>> ENDPROC(acmeSoC_cpu_suspend)
>>
>> Nothing has that - because you can't execute that ldmfd after the call
>> to cpu_suspend returns. I don't think you've understood what I said on
>> that subject in the previous thread.
>>
>
> Ok, to illustrate a bit more, what is ok and what not.
Actually, we can do something about cpu_suspend.
Currently cpu_suspend is not like a normal C function - when it's called
it returns normally to a bunch of code which is not expected to return.
The return path is via code pointed to by 'r3'.
It also corrupts a bunch of registers in ways which make it non-compliant
with a C API.
If we do make this complaint as a normal C-like function, it eliminates
this register saving. We also swap 'lr' and 'r3', so cpu_suspend
effectively only returns to following code on resume - and r3 points
to the suspend code.
So, this becomes:
ENTRY(acmeSoC_cpu_suspend)
stmfd sp!, {lr}
adr r3, soc_finish_suspend
bl cpu_suspend
ldmfd sp!, {pc}
ENDPROC(acmeSoC_cpu_suspend)
soc_finish_suspend:
blah
blah
put soc to sleep
never return
or even:
static void soc_suspend(void)
{
[soc specific preparation]
cpu_suspend(0, PLAT_PHYS_OFFSET - PAGE_OFFSET,
soc_suspend_arg, soc_suspend_fn);
[soc specific cleanup ]
}
where soc_suspend_fn can be either assembly or C code - but must never
return. Patches will follow this evening.
^ permalink raw reply [flat|nested] 21+ messages in thread
* [RFC PATCH v5] ARM hibernation / suspend-to-disk (fwd)
2011-06-13 16:44 ` Russell King - ARM Linux
@ 2011-06-15 13:35 ` Frank Hofmann
2011-06-16 21:31 ` Russell King - ARM Linux
` (2 more replies)
0 siblings, 3 replies; 21+ messages in thread
From: Frank Hofmann @ 2011-06-15 13:35 UTC (permalink / raw)
To: linux-arm-kernel
On Mon, 13 Jun 2011, Russell King - ARM Linux wrote:
> On Mon, Jun 13, 2011 at 02:20:12PM +0100, Frank Hofmann wrote:
>>
>>
>> On Mon, 13 Jun 2011, Russell King - ARM Linux wrote:
>>
>>> On Mon, Jun 13, 2011 at 01:04:02PM +0100, Frank Hofmann wrote:
>>>> To make it clear: IF AND ONLY IF your suspend(-to-ram) func looks like:
>>>>
>>>> ENTRY(acmeSoC_cpu_suspend)
>>>> stmfd sp!, {r4-r12,lr}
>>>> ldr r3, resume_mmu_done
>>>> bl cpu_suspend
>>>> resume_mmu_done:
>>>> ldmfd sp!, {r3-r12,pc}
>>>> ENDPROC(acmeSoC_cpu_suspend)
>>>
>>> Nothing has that - because you can't execute that ldmfd after the call
>>> to cpu_suspend returns. I don't think you've understood what I said on
>>> that subject in the previous thread.
>>>
>>
>> Ok, to illustrate a bit more, what is ok and what not.
>
> Actually, we can do something about cpu_suspend.
>
> Currently cpu_suspend is not like a normal C function - when it's called
> it returns normally to a bunch of code which is not expected to return.
> The return path is via code pointed to by 'r3'.
>
> It also corrupts a bunch of registers in ways which make it non-compliant
> with a C API.
>
> If we do make this complaint as a normal C-like function, it eliminates
> this register saving. We also swap 'lr' and 'r3', so cpu_suspend
> effectively only returns to following code on resume - and r3 points
> to the suspend code.
Hi Russell,
this change is perfect; with this, the hibernation support code turns into
the attached.
That's both better and simpler to perform a full suspend/resume cycle (via
resetting in the cpu_suspend "finisher") after the snapshot image has been
created, instead of shoehorning a return into this.
I've tested the attached on v6 (samsung) and v7 (omap3 nonsecure - yes I
know ...) kernels that have the cpu_suspend changes in you've posted
Monday.
It does what it's supposed to do. And yes, aware that's not enough yet,
this is only an attempt to address the "how to snapshot the core state",
other outstanding issues will be addressed later.
It'd be great to know why this makes your toenails curl so much ...
Anyway, this again shows that as far as the core SoC state is concerned,
the only difference between the hibernation snapshot and the s2ram soc
suspend side are what the "finisher" does:
hibernate: s2ram:
swsusp_save() low power self-refresh settings, ...
<reset> <poweroff>
Why would calling swsusp_save() not be acceptable in this context ? It's
supposed to run in a restricted env (no ints, no scheduling, ...) anyway.
FrankH.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: hibernation-15Jun2011.patch
Type: text/x-diff
Size: 5726 bytes
Desc:
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20110615/b7790fe8/attachment-0001.bin>
^ permalink raw reply [flat|nested] 21+ messages in thread
* [RFC PATCH v5] ARM hibernation / suspend-to-disk (fwd)
2011-06-15 13:35 ` Frank Hofmann
@ 2011-06-16 21:31 ` Russell King - ARM Linux
2011-06-20 12:32 ` Frank Hofmann
2011-06-29 14:52 ` Matthieu CASTET
2011-07-05 12:37 ` Matthieu CASTET
2 siblings, 1 reply; 21+ messages in thread
From: Russell King - ARM Linux @ 2011-06-16 21:31 UTC (permalink / raw)
To: linux-arm-kernel
On Wed, Jun 15, 2011 at 02:35:26PM +0100, Frank Hofmann wrote:
> this change is perfect; with this, the hibernation support code turns
> into the attached.
Should I assume that's an ack for all the patches?
> That's both better and simpler to perform a full suspend/resume cycle
> (via resetting in the cpu_suspend "finisher") after the snapshot image
> has been created, instead of shoehorning a return into this.
It's now not soo difficult to have an error code returned from the
finisher function - the only thing we have to make sure is that
the cpu_do_suspend helper just saves state and does not make any
state changes.
We can then do this, which makes it possible for the finisher to
return, and we propagate its return value. We also ensure that a
path through from cpu_resume will result in a zero return value
from cpu_suspend.
This isn't an invitation for people to make the S2RAM path return
after they time out waiting for suspend to happen - that's potentially
dangerous because in that case the suspend may happen while we're
resuming devices which wouldn't be nice.
diff -u b/arch/arm/kernel/sleep.S b/arch/arm/kernel/sleep.S
--- b/arch/arm/kernel/sleep.S
+++ b/arch/arm/kernel/sleep.S
@@ -12,7 +12,6 @@
* r1 = v:p offset
* r2 = suspend function arg0
* r3 = suspend function
- * Note: does not return until system resumes
*/
ENTRY(cpu_suspend)
stmfd sp!, {r4 - r11, lr}
@@ -26,7 +25,7 @@
#endif
mov r6, sp @ current virtual SP
sub sp, sp, r5 @ allocate CPU state on stack
- mov r0, sp @ save pointer
+ mov r0, sp @ save pointer to CPU save block
add ip, ip, r1 @ convert resume fn to phys
stmfd sp!, {r1, r6, ip} @ save v:p, virt SP, phys resume fn
ldr r5, =sleep_save_sp
@@ -55,10 +54,17 @@
#else
bl __cpuc_flush_kern_all
#endif
+ adr lr, BSYM(cpu_suspend_abort)
ldmfd sp!, {r0, pc} @ call suspend fn
ENDPROC(cpu_suspend)
.ltorg
+cpu_suspend_abort:
+ ldmia sp!, {r1 - r3} @ pop v:p, virt SP, phys resume fn
+ mov sp, r2
+ ldmfd sp!, {r4 - r11, pc}
+ENDPROC(cpu_suspend_abort)
+
/*
* r0 = control register value
* r1 = v:p offset (preserved by cpu_do_resume)
@@ -88,6 +94,7 @@
cpu_resume_after_mmu:
str r5, [r2, r4, lsl #2] @ restore old mapping
mcr p15, 0, r0, c1, c0, 0 @ turn on D-cache
+ mov r0, #0 @ return zero on success
ldmfd sp!, {r4 - r11, pc}
ENDPROC(cpu_resume_after_mmu)
^ permalink raw reply [flat|nested] 21+ messages in thread
* [RFC PATCH v5] ARM hibernation / suspend-to-disk (fwd)
2011-06-16 21:31 ` Russell King - ARM Linux
@ 2011-06-20 12:32 ` Frank Hofmann
2011-06-21 14:35 ` Russell King - ARM Linux
0 siblings, 1 reply; 21+ messages in thread
From: Frank Hofmann @ 2011-06-20 12:32 UTC (permalink / raw)
To: linux-arm-kernel
On Thu, 16 Jun 2011, Russell King - ARM Linux wrote:
> On Wed, Jun 15, 2011 at 02:35:26PM +0100, Frank Hofmann wrote:
>> this change is perfect; with this, the hibernation support code turns
>> into the attached.
>
> Should I assume that's an ack for all the patches?
Sorry the late reply, been away.
I've only tested on s3c64xx (for s2ram and s2disk) and omap3 (s2disk only
due to the omap code not having been "genericized" yet), the changes are
ok there.
The remainder apply and compile ok.
If that's sufficient, then:
Acked-by: Frank Hofmann <frank.hofmann@tomtom.com>
>
>> That's both better and simpler to perform a full suspend/resume cycle
>> (via resetting in the cpu_suspend "finisher") after the snapshot image
>> has been created, instead of shoehorning a return into this.
>
> It's now not soo difficult to have an error code returned from the
> finisher function - the only thing we have to make sure is that
> the cpu_do_suspend helper just saves state and does not make any
> state changes.
>
> We can then do this, which makes it possible for the finisher to
> return, and we propagate its return value. We also ensure that a
> path through from cpu_resume will result in a zero return value
> from cpu_suspend.
>
> This isn't an invitation for people to make the S2RAM path return
> after they time out waiting for suspend to happen - that's potentially
> dangerous because in that case the suspend may happen while we're
> resuming devices which wouldn't be nice.
You're right there's some risk that the ability to return an error here is
misinterpreted as an invitation to use error returns for indicating state
machine conditions.
What I'm wondering about is the usecase for having an error return
opportunity in this case (beyond reporting it as such). Isn't it rather so
that most finishers would succeed and at best do a "BUG_ON()" at failure,
because system state then isn't such to make it trivially recoverable ?
For hibernation, the ability to force the entire down/up transition before
writing the snapshot image out is actually very beneficial, for
reliability - one knows that the device/cpu side of suspend/resume has
already worked when the snapshot is being written, without having to wait
for reboot/image load/resume to test that. One would want to go through
suspend/resume even if the memory snapshot operation, swsusp_save, errors.
A failure of swsusp_save doesn't make suspend/resume itself a failure,
therefore it's desirable to propagate that return code in other ways (and
keep the finisher "unconditional").
I'm not opposed to this addition as such, but I'm curious:
* If an error occurs, how can the caller of cpu_suspend recover from it ?
* What's the state the system is in after an error in this codepath ?
* What subsystems / users would do anything else with it than BUG_ON() ?
Also, consider possible errors in the SoC-specific code on the resume
side; situations like a failure to perform SoC-iROM-calls for e.g. an
attempted secure state restore would result in errors that can't be
propagated by this mechanism; i.e. there are still failure modes which
require platform-specific intervention of sorts, and platform-specific
error propagation/handling, even were cpu_suspend to return error codes.
FrankH.
>
> diff -u b/arch/arm/kernel/sleep.S b/arch/arm/kernel/sleep.S
> --- b/arch/arm/kernel/sleep.S
> +++ b/arch/arm/kernel/sleep.S
> @@ -12,7 +12,6 @@
> * r1 = v:p offset
> * r2 = suspend function arg0
> * r3 = suspend function
> - * Note: does not return until system resumes
> */
> ENTRY(cpu_suspend)
> stmfd sp!, {r4 - r11, lr}
> @@ -26,7 +25,7 @@
> #endif
> mov r6, sp @ current virtual SP
> sub sp, sp, r5 @ allocate CPU state on stack
> - mov r0, sp @ save pointer
> + mov r0, sp @ save pointer to CPU save block
> add ip, ip, r1 @ convert resume fn to phys
> stmfd sp!, {r1, r6, ip} @ save v:p, virt SP, phys resume fn
> ldr r5, =sleep_save_sp
> @@ -55,10 +54,17 @@
> #else
> bl __cpuc_flush_kern_all
> #endif
> + adr lr, BSYM(cpu_suspend_abort)
> ldmfd sp!, {r0, pc} @ call suspend fn
> ENDPROC(cpu_suspend)
> .ltorg
>
> +cpu_suspend_abort:
> + ldmia sp!, {r1 - r3} @ pop v:p, virt SP, phys resume fn
> + mov sp, r2
> + ldmfd sp!, {r4 - r11, pc}
> +ENDPROC(cpu_suspend_abort)
> +
> /*
> * r0 = control register value
> * r1 = v:p offset (preserved by cpu_do_resume)
> @@ -88,6 +94,7 @@
> cpu_resume_after_mmu:
> str r5, [r2, r4, lsl #2] @ restore old mapping
> mcr p15, 0, r0, c1, c0, 0 @ turn on D-cache
> + mov r0, #0 @ return zero on success
> ldmfd sp!, {r4 - r11, pc}
> ENDPROC(cpu_resume_after_mmu)
>
>
>
^ permalink raw reply [flat|nested] 21+ messages in thread
* [RFC PATCH v5] ARM hibernation / suspend-to-disk (fwd)
2011-06-20 12:32 ` Frank Hofmann
@ 2011-06-21 14:35 ` Russell King - ARM Linux
0 siblings, 0 replies; 21+ messages in thread
From: Russell King - ARM Linux @ 2011-06-21 14:35 UTC (permalink / raw)
To: linux-arm-kernel
On Mon, Jun 20, 2011 at 01:32:47PM +0100, Frank Hofmann wrote:
> I've only tested on s3c64xx (for s2ram and s2disk) and omap3 (s2disk only
> due to the omap code not having been "genericized" yet), the changes are
> ok there.
> The remainder apply and compile ok.
>
> If that's sufficient, then:
> Acked-by: Frank Hofmann <frank.hofmann@tomtom.com>
I've added that to the core stuff and s3c64xx.
> You're right there's some risk that the ability to return an error here
> is misinterpreted as an invitation to use error returns for indicating
> state machine conditions.
Well, an error return undoes (and probably corrupts) the state which
cpu_suspend saved, so it wouldn't be useful for state machine stuff -
I wonder whether we should poison the saved pointers just to reinforce
this point.
> What I'm wondering about is the usecase for having an error return
> opportunity in this case (beyond reporting it as such). Isn't it rather
> so that most finishers would succeed and at best do a "BUG_ON()" at
> failure, because system state then isn't such to make it trivially
> recoverable ?
For s2ram, there's no reason at this point to fail. The only thing left
to do at this point is to do whatever is required to cause the system to
enter the low power mode.
In the case where you need to place the SDRAM into self refresh mode
manually, the timing of stuff after self refresh mode has been entered
to the point where power is cut to the CPU is normally well defined,
and if for whatever reason power doesn't get cut, there's very little
which can be done to re-awake the system (you'd have to ensure that
the code to do that was already in the I-cache and whatever data was
required was already in registers.)
And as I mentioned, if you timeout waiting for the system to power off,
and you've done everything you should have done, are you sure that the
system won't power off on you unexpectedly if you return with an error,
which would then mean you have corrupted state saved (and possibly
corrupted filesystems.)
So, I don't think S2RAM would have any practical use for an error return
path. It's more for hibernation.
> For hibernation, the ability to force the entire down/up transition
> before writing the snapshot image out is actually very beneficial, for
> reliability - one knows that the device/cpu side of suspend/resume has
> already worked when the snapshot is being written, without having to wait
> for reboot/image load/resume to test that.
It's not a test of the suspend/resume path though - device state is very
different between suspending in some way followed by an immediate resume
without resetting, and a real suspend, power off, resume cycle.
The former doesn't really test the resume paths - a register which has
been forgotten won't be found by any other way than cutting the power,
and you'll only ever find that on a proper resume-from-power-off.
> I'm not opposed to this addition as such, but I'm curious:
> * If an error occurs, how can the caller of cpu_suspend recover from it ?
If an error occurs from cpu_suspend(), then the caller needs to undo any
modification to state which it did while saving, and return an error.
> * What's the state the system is in after an error in this codepath ?
We can arrange for another callback into CPU specific code to sort out
anything they've done - iow, an error return from cpu_suspend should
ensure that we have the same state present as we had at the point it
was called. We currently do not need that as cpu_suspend() just saves
state without modifying anything, but if we ended up with a CPU which
required stuff to be modified, we'd have to undo those modifications
before returning an error.
> * What subsystems / users would do anything else with it than BUG_ON() ?
The error code from the platform_suspend_ops ->enter method is already
dealt with - by going through the resume steps before returning the
error code. Whether hibernate has similar functionality I don't know.
What I do think is that if hibernate needs to return an error code, we'd
better do that without doing things like taking the MMU down to run the
resume paths in order to do that. If we have some error to propagate,
we want to propagate it back as easily as possible.
^ permalink raw reply [flat|nested] 21+ messages in thread
* [RFC PATCH v5] ARM hibernation / suspend-to-disk (fwd)
2011-06-15 13:35 ` Frank Hofmann
2011-06-16 21:31 ` Russell King - ARM Linux
@ 2011-06-29 14:52 ` Matthieu CASTET
2011-06-29 15:14 ` Frank Hofmann
2011-07-05 12:37 ` Matthieu CASTET
2 siblings, 1 reply; 21+ messages in thread
From: Matthieu CASTET @ 2011-06-29 14:52 UTC (permalink / raw)
To: linux-arm-kernel
Frank Hofmann a ?crit :
> On Mon, 13 Jun 2011, Russell King - ARM Linux wrote:
>
> Hi Russell,
>
>
> this change is perfect; with this, the hibernation support code turns into
> the attached.
>
> That's both better and simpler to perform a full suspend/resume cycle (via
> resetting in the cpu_suspend "finisher") after the snapshot image has been
> created, instead of shoehorning a return into this.
>
> FrankH.
>
> +
> +u8 __swsusp_resume_stk[PAGE_SIZE/2] __nosavedata;
It look like dangerous : there is no alignment constraint, but the stack should
be aligned on a 8 Bytes.
Matthieu
^ permalink raw reply [flat|nested] 21+ messages in thread
* [RFC PATCH v5] ARM hibernation / suspend-to-disk (fwd)
2011-06-29 14:52 ` Matthieu CASTET
@ 2011-06-29 15:14 ` Frank Hofmann
2011-06-29 20:08 ` Will Deacon
0 siblings, 1 reply; 21+ messages in thread
From: Frank Hofmann @ 2011-06-29 15:14 UTC (permalink / raw)
To: linux-arm-kernel
On Wed, 29 Jun 2011, Matthieu CASTET wrote:
> Frank Hofmann a ?crit :
>> On Mon, 13 Jun 2011, Russell King - ARM Linux wrote:
>>
>> Hi Russell,
>>
>>
>> this change is perfect; with this, the hibernation support code turns into
>> the attached.
>>
>> That's both better and simpler to perform a full suspend/resume cycle (via
>> resetting in the cpu_suspend "finisher") after the snapshot image has been
>> created, instead of shoehorning a return into this.
>>
>> FrankH.
>
>
>>
>> +
>> +u8 __swsusp_resume_stk[PAGE_SIZE/2] __nosavedata;
> It look like dangerous : there is no alignment constraint, but the stack should
> be aligned on a 8 Bytes.
Uh - sorry. I used to have both the __nosavedata and
__attribute__((__aligned__(PAGE_SIZE/2))) attributes there. That must've
gone lost at one point.
It's an artifact of the build that things turn out ok by default; the
__nosavedata forces a separate section (page), and arch/arm is linked
before kernel/power (the other user of __nosavedata), hence this block,
due to the way the kernel build works, ends up just fine.
But as you say, not by intent / declaration.
Have you seen Will Deacon's suggested kexec changes ? That keeps a "reset
stack" page around, _elsewhere_, and I've been considering using that. In
the end, all swsusp_arch_resume() really requires is a stack page that's
guaranteed to be outside the target kernel data, thereby left alone by the
restore. __nosavedata is merely one way.
>
>
> Matthieu
>
Thanks,
FrankH.
^ permalink raw reply [flat|nested] 21+ messages in thread
* [RFC PATCH v5] ARM hibernation / suspend-to-disk (fwd)
2011-06-29 15:14 ` Frank Hofmann
@ 2011-06-29 20:08 ` Will Deacon
0 siblings, 0 replies; 21+ messages in thread
From: Will Deacon @ 2011-06-29 20:08 UTC (permalink / raw)
To: linux-arm-kernel
Hi Frank,
On Wed, Jun 29, 2011 at 04:14:23PM +0100, Frank Hofmann wrote:
> Have you seen Will Deacon's suggested kexec changes ? That keeps a "reset
> stack" page around, _elsewhere_, and I've been considering using that. In
> the end, all swsusp_arch_resume() really requires is a stack page that's
> guaranteed to be outside the target kernel data, thereby left alone by the
> restore. __nosavedata is merely one way.
For what it's worth, in v4 of that series (hopefully I'll post it soon)
I'm starting to think about SMP kexec which necessitates that the reserved
stack page is placed in a fixed location. I'm planning to memblock_reserve
the page immediately below swapper for this.
Will
^ permalink raw reply [flat|nested] 21+ messages in thread
* [RFC PATCH v5] ARM hibernation / suspend-to-disk (fwd)
2011-06-15 13:35 ` Frank Hofmann
2011-06-16 21:31 ` Russell King - ARM Linux
2011-06-29 14:52 ` Matthieu CASTET
@ 2011-07-05 12:37 ` Matthieu CASTET
[not found] ` <2C577202CB5719438D4E9608C565CB2C01B69D7F@NL-EXC-07.intra.local>
2 siblings, 1 reply; 21+ messages in thread
From: Matthieu CASTET @ 2011-07-05 12:37 UTC (permalink / raw)
To: linux-arm-kernel
Frank Hofmann a ?crit :
> On Mon, 13 Jun 2011, Russell King - ARM Linux wrote:
>
>> On Mon, Jun 13, 2011 at 02:20:12PM +0100, Frank Hofmann wrote:
>>>
>>> On Mon, 13 Jun 2011, Russell King - ARM Linux wrote:
>>>
>>>> On Mon, Jun 13, 2011 at 01:04:02PM +0100, Frank Hofmann wrote:
>>>>> To make it clear: IF AND ONLY IF your suspend(-to-ram) func looks like:
>>>>>
>>>>> ENTRY(acmeSoC_cpu_suspend)
>>>>> stmfd sp!, {r4-r12,lr}
>>>>> ldr r3, resume_mmu_done
>>>>> bl cpu_suspend
>>>>> resume_mmu_done:
>>>>> ldmfd sp!, {r3-r12,pc}
>>>>> ENDPROC(acmeSoC_cpu_suspend)
>>>> Nothing has that - because you can't execute that ldmfd after the call
>>>> to cpu_suspend returns. I don't think you've understood what I said on
>>>> that subject in the previous thread.
>>>>
>>> Ok, to illustrate a bit more, what is ok and what not.
>> Actually, we can do something about cpu_suspend.
>>
>> Currently cpu_suspend is not like a normal C function - when it's called
>> it returns normally to a bunch of code which is not expected to return.
>> The return path is via code pointed to by 'r3'.
>>
>> It also corrupts a bunch of registers in ways which make it non-compliant
>> with a C API.
>>
>> If we do make this complaint as a normal C-like function, it eliminates
>> this register saving. We also swap 'lr' and 'r3', so cpu_suspend
>> effectively only returns to following code on resume - and r3 points
>> to the suspend code.
>
> Hi Russell,
>
>
> this change is perfect; with this, the hibernation support code turns into
> the attached.
> That's both better and simpler to perform a full suspend/resume cycle (via
> resetting in the cpu_suspend "finisher") after the snapshot image has been
> created, instead of shoehorning a return into this.
>
>
> +static void notrace __swsusp_arch_restore_image(void)
> +{
> + extern struct pbe *restore_pblist;
> + struct pbe *pbe;
> +
> + cpu_switch_mm(swapper_pg_dir, &init_mm);
> +
> + for (pbe = restore_pblist; pbe; pbe = pbe->next)
> + copy_page(pbe->orig_address, pbe->address);
> +
One question : isn't dangerous to modify the code where we are running ?
I believe the code shouldn't change too much between the kernel that do the
resume and the resumed kernel and the copy routine should fit in the instruction
cache, but I want to be sure it doesn't cause any problem on recent arm cores
(instruction prefetching , ...)
Matthieu
^ permalink raw reply [flat|nested] 21+ messages in thread
* [RFC PATCH v5] ARM hibernation / suspend-to-disk (fwd)
[not found] ` <2C577202CB5719438D4E9608C565CB2C01B69D7F@NL-EXC-07.intra.local>
@ 2011-07-05 17:09 ` Matthieu CASTET
0 siblings, 0 replies; 21+ messages in thread
From: Matthieu CASTET @ 2011-07-05 17:09 UTC (permalink / raw)
To: linux-arm-kernel
Frank Hofmann a ?crit :
> -----Original Message-----
> From: Matthieu CASTET [mailto:matthieu.castet at parrot.com]
> Frank Hofmann a ?crit :
>> [ ... ]
>> > +static void notrace __swsusp_arch_restore_image(void)
>> > +{
>> > + extern struct pbe *restore_pblist;
>> > + struct pbe *pbe;
>> > +
>> > + cpu_switch_mm(swapper_pg_dir, &init_mm);
>> > +
>> > + for (pbe = restore_pblist; pbe; pbe = pbe->next)
>> > + copy_page(pbe->orig_address, pbe->address);
>> > +
>>
>> One question : isn't dangerous to modify the code where we are running ?
>>
>> I believe the code shouldn't change too much between the kernel that
> do the
>> resume and the resumed kernel and the copy routine should fit in the
> instruction
>> cache, but I want to be sure it doesn't cause any problem on recent
> arm cores
>> (instruction prefetching , ...)
>>
>>
>> Matthieu
>
> Hi Matthieu,
>
> this isn't new behaviour to _this_ rev of the patch ...
yes
>
> and yes, it is dangerous to modify code where you're running. Except
> that this isn't happening in the current environment;
You are modifying it by putting the same code (modulo dynamic patching on the
code (ftrace, kprobe, ...)).
> If you're resuming via some other
> mechanism but the kernel's snapshot image loading code (and only jump
> into swsusp_arch_resume to kickstart resume) then it's up to you how you
> get the kernel text into place.
Yes.
> I've not experimented with resuming "foreign" images; how would one
> create such, and bypass the checks on load ?
I wasn't suggesting that.
>
> It's less of a problem for the copy loop itself, really, as that's
> definitely cache-hot. But it's an issue for what happens _after_ the
> copy loop. If the code for cpu_resume / cpu_reset is not at the places
> where the resum-ing code expects it to be (i.e. if there's a mismatch in
> the resuming and to-be-resumed kernels wrt. to that), then things will
> jump to code nirvana.
>
> Why are you asking about this ?
While reading the code I was surprised of that. And that there weren't any
comment about it.
Looking at other implementations, only x86_64 seems to need to relocate the copy
code.
Matthieu
^ permalink raw reply [flat|nested] 21+ messages in thread
* [RFC PATCH v5] ARM hibernation / suspend-to-disk (fwd)
2011-06-13 12:04 [RFC PATCH v5] ARM hibernation / suspend-to-disk (fwd) Frank Hofmann
2011-06-13 12:26 ` Russell King - ARM Linux
@ 2011-09-30 7:48 ` Barry Song
1 sibling, 0 replies; 21+ messages in thread
From: Barry Song @ 2011-09-30 7:48 UTC (permalink / raw)
To: linux-arm-kernel
Hi Frank,
2011/6/13 Frank Hofmann <frank.hofmann@tomtom.com>:
> Hi,
>
> to make one thing clear to start with:
>
> This is not a proposal to integrate the hibernation feature into mainline.
>
> It's not ripe for that because it's unclear what exactly the differences are
> between what the hibernation / S2RAM codepaths have to do, and/or how much
> code sharing between these codepaths is advisable.
>
>
> Therefore, I'm merely putting this out as-is as a reference / base for those
> who want to do their own experiments with the feature.
>
> Prerequisites:
>
> * The patch requires a working cpu_reset(); for v6/v7, that's in Will
> ?Deacon's patch series from last week.
>
> * It also requires being able to take the address of cpu_reset and
> ?on MULTI_CPU configs therefore, again see Will Deacon's patch series.
>
> * It uses on cpu_suspend() / cpu_resume(), therefore a recent-enough
> ?kernel (or a port of those to whatever you're using) is required.
>
>
> Important / Limitations:
>
> A) For platforms that currently use cpu_suspend/cpu_resume in their s2ram
> ?codepaths AND DO NOTHING ELSE BEFORE AND NOTHING ELSE AFTER THAT BUT TO
> ?"ENTER LOW POWER", the way the hibernation state snapshot for the CPU
> ?core is done by this patch is sufficient.
>
> ?To make it clear: IF AND ONLY IF your suspend(-to-ram) func looks like:
>
> ? ? ? ?ENTRY(acmeSoC_cpu_suspend)
> ? ? ? ? ? ? ? ?stmfd ? sp!, {r4-r12,lr}
> ? ? ? ? ? ? ? ?ldr ? ? r3, resume_mmu_done
> ? ? ? ? ? ? ? ?bl ? ? ?cpu_suspend
> ? ? ? ?resume_mmu_done:
> ? ? ? ? ? ? ? ?ldmfd ? sp!, {r3-r12,pc}
> ? ? ? ?ENDPROC(acmeSoC_cpu_suspend)
>
> ?then this patch is ok to provide hibernation support for your CPU core.
>
> ?In all other cases, item B).
>
> ?IN ALL CASES, read item C) below; there's more than the core to the SoC.
>
> B) If there's any cpu-specific / SoC-specific state that needs (re)init
> ?over a suspend-to-disk/resume-from-disk cycle, this patch is incomplete
> ?because it provides no hooks/code for that.
>
> ?This is the case e.g. for "secure" SoCs that have different sets of
> ?control registers and/or different CR reg access patterns.
>
> ?It's also the case e.g. for SoCs with L2 caches as the activation
> ?sequence there is SoC-dependent; a full off-on cycle for L2 is not done
> ?by the hibernation support code.
>
> ?It's also the case if the SoC requires steps on wakeup _before_ the
> ?"generic" parts done by cpu_suspend / cpu_resume can work correctly.
>
> ?(OMAP is an example of such a SoC; the patch "works" on OMAP in the
> ?sense that it gets you a non-secure OMAP back from hibernation but as
> ?mentioned, your mileage may vary; I for example don't know what the
> ?consequences ?of not disabling / reenabling the L2 cache over cpu_reset
> ?are)
>
> C) The current low-power handling may perform SoC-specific tasks such
> ?as GPIO state handling, which is currently also not addressed by this
> ?patch; the assumption is rather that device suspend/resume deals with
> ?this. That is not guaranteed to be complete / sufficient - if your SoC
> ?and/or your device drivers have particular needs in this area, you can
> ?put hooks performing these actions into save_/restore_processor_state().
>
> D) If you wish to extend this to a SoC for which the generic CPU core
> ?hooks (i.e. what cpu_suspend/resume provide) are either insufficient
> ?or unavailable, hook your own state snapshot mechanism into the places
> ?where this code currently calls cpu_suspend and cpu_resume. The main
> ?assumption by the assembly code within swusp_arch_resume() is that
> ?__swsusp_arch_restore_image() returns to its caller with the stack
> ?restored - how you achieve that is up to you, the patch as-is does it
> ?by cpu_reset(cpu_resume) but your mileage may vary.
>
>
> I will, at this point, not send further iterations of this patch.
>
> I'll answer questions about it though, if there are any.
i did bring-up prima2(cortex-a9) swsusp hibernation support based on
your patch. i am considering whether we can have some ways to make the
resume faster.
Now the resume flow is:
[1] poweron -> bootloader -> kernel -> all boot and device probed ->
late_init() -> loading snapshot from disk to memory -> resume devices
and software
Is it possible we make it:
[2] poweron -> bootloader -> loading snapshot from disk to memory ->
resume devices and software
Then the sub-process "bootloader -> kernel -> all boot and device
probed -> late_init()" will be eliminated and time to boot kernel will
not be needed too.
the flow [2] is more platform-related. so it is probably we can use
platform_hibernation_ops to handle. but it can be generic as well.
>
>
> Thanks for all the comments during the previous threads - learned a lot !
>
>
> Best regards,
> FrankH.
-barry
^ permalink raw reply [flat|nested] 21+ messages in thread
end of thread, other threads:[~2011-09-30 7:48 UTC | newest]
Thread overview: 21+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-06-13 12:04 [RFC PATCH v5] ARM hibernation / suspend-to-disk (fwd) Frank Hofmann
2011-06-13 12:26 ` Russell King - ARM Linux
2011-06-13 12:40 ` Frank Hofmann
2011-06-13 13:20 ` Frank Hofmann
2011-06-13 13:56 ` Dave Martin
2011-06-13 13:56 ` Dave Martin
2011-06-13 15:34 ` Frank Hofmann
2011-06-13 15:34 ` Frank Hofmann
2011-06-13 16:11 ` Frank Hofmann
2011-06-13 16:11 ` Frank Hofmann
2011-06-13 16:44 ` Russell King - ARM Linux
2011-06-15 13:35 ` Frank Hofmann
2011-06-16 21:31 ` Russell King - ARM Linux
2011-06-20 12:32 ` Frank Hofmann
2011-06-21 14:35 ` Russell King - ARM Linux
2011-06-29 14:52 ` Matthieu CASTET
2011-06-29 15:14 ` Frank Hofmann
2011-06-29 20:08 ` Will Deacon
2011-07-05 12:37 ` Matthieu CASTET
[not found] ` <2C577202CB5719438D4E9608C565CB2C01B69D7F@NL-EXC-07.intra.local>
2011-07-05 17:09 ` Matthieu CASTET
2011-09-30 7:48 ` Barry Song
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.