From: frank.hofmann@tomtom.com (Frank Hofmann)
To: linux-arm-kernel@lists.infradead.org
Subject: [RFC PATCH v3] ARM hibernation/suspend-to-disk support
Date: Tue, 31 May 2011 12:50:55 +0100 (BST) [thread overview]
Message-ID: <alpine.DEB.2.00.1105311020130.5486@localhost6.localdomain6> (raw)
In-Reply-To: <alpine.LFD.2.00.1105271501220.3207@xanadu.home>
On Fri, 27 May 2011, Nicolas Pitre wrote:
> On Fri, 27 May 2011, Frank Hofmann wrote:
>
>> /*
>> * r0 = control register value
>> * r1 = v:p offset (preserved by cpu_do_resume)
>> + * if this is zero, do not reenable MMU (it's on)
>
> This is wrong. It is well possible for this to be zero when the MMU is
> active.
>
> The best way to determine if MMU is on or off is:
>
> mrc p15, 0, rx, c1, c0 @ load ctrl reg
> tst rx, #1 @ test M bit
Ah, thanks. I had thought only MMU-less kernels will run on identity but
you're right of course there's nothing to stop it as such.
This one:
==============================================================================
diff --git a/arch/arm/kernel/sleep.S b/arch/arm/kernel/sleep.S
index 6398ead..a793644 100644
--- a/arch/arm/kernel/sleep.S
+++ b/arch/arm/kernel/sleep.S
@@ -75,6 +75,9 @@ ENDPROC(cpu_suspend)
* r3 = L1 section flags
*/
ENTRY(cpu_resume_mmu)
+ mrc p15, 0, r4, c1, c0, 0
+ tst r4, #CR_M
+ bne 0f @ return if MMU already on
adr r4, cpu_resume_turn_mmu_on
mov r4, r4, lsr #20
orr r3, r3, r4, lsl #20
@@ -96,6 +99,7 @@ cpu_resume_turn_mmu_on:
ENDPROC(cpu_resume_turn_mmu_on)
cpu_resume_after_mmu:
str r5, [r2, r4, lsl #2] @ restore old mapping
+0:
mcr p15, 0, r0, c1, c0, 0 @ turn on D-cache
mov pc, lr
ENDPROC(cpu_resume_after_mmu)
==============================================================================
does indeed do that part of the job.
>
>> I wonder; is there a proper/suggested way to switch MMU off (and not end in
>> binary nirvana), to have the reentry / reenable work ?
>
> This is slightly complicated. You first need to turn of and disable the
> caches, and ideally set up a 1:1 mapping for the transition. There are
> cpu_proc_fin() and cpu_reset(branch_location).
Hmm, just looked through that. One of the issues with this is my usecase -
ARM11x6 and Cortex-A8/9, for which these are cpu_v[67]_reset() - a no-op
(in mainline / rmk devel-stable). I.e. neither cpu_proc_fin() nor
cpu_reset() on v6/v7 currently switch the MMU off. The older chips do ...
Anyway, the setup for resume after hibernation at the moment is:
- swsusp_arch_resume switches to swapper_pg_dir
(which is guaranteed to be kernel flat addresses ?!)
- image restoration
[ caches should probably be flushed / turned off after this ? ]
- cpu_do_resume() restores pre-suspend TTBR
(which in effect is a cpu_switch_mm)
- cpu_resume_mmu bypassed because MMU already on
But that means as part of the resume, a context switch is done anyway.
Which sort of leads to the question whether the 1:1 mapping for the switch
off case is really required; wouldn't it be acceptable to simply turn the
MMU off and jump to the physical address of cpu_do_resume() instead ?
Something like:
[ caches off ... ]
@ assume r0 == phys addr of restore buffer (however retrieved)
ldr r1, =virt_addr_of_restore_buffer @ known
sub r2, r1, r0 @ calc v:p offset
ldr r3, =cpu_do_resume @ virt func addr
sub r3, r3, r2 @ to phys
mrc p15, 0, r1, cr0, cr1, 0
bic r1, #CR_M
adr lr, =post_resume @ load virtual
mcr r15, 0, r1, cr0, cr1, 0 @ MMU off
crit: mov pc, r3 @ jump phys
post_resume:
[ continue processing when done / returned ]
Or is it necessary to have a 1:1 mapping for 'crit:' when switching the
MMU off, to make sure one actually reaches the jump ?
>
> You may also investigate how kexec is handled which purpose is to let
> the kernel boot another kernel.
machine_kexec() you mean ? I vaguely remember having read that to get this
working on v6/v7 CPUs one needs non-mainline patches, is that still so ?
The current fin / reset codepaths for v6/v7 don't turn the MMU off,
anyway.
Thanks for the pointer. Reading that, it looks like flushing / disabling
all caches is necessary before entering/resuming the target ?
I'm starting to wonder whether for a first-stab at hibernation support on
ARM, the ability to resume non-identical kernels / resume not via the
kernel hibernation restore codepaths (i.e. invocation via bootloader) is
required.
As Rafael answered a while back, to make that work a temporary MMU
initialization / setup is necessary for the image restoration. The
current code assumes swapper_pg_dir has been set up, and maps the entire
kernel heap; how true is that assumption, actually, at "kernel entry" ?
Thanks,
FrankH.
>
>
> Nicolas
>
next prev parent reply other threads:[~2011-05-31 11:50 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-05-25 13:16 [RFC PATCH v3] ARM hibernation/suspend-to-disk support Frank Hofmann
2011-05-27 15:01 ` Frank Hofmann
2011-05-27 19:27 ` Nicolas Pitre
2011-05-31 11:50 ` Frank Hofmann [this message]
2011-06-02 22:18 ` [linux-pm] " Pavel Machek
2011-06-14 8:00 ` Frank Hofmann
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=alpine.DEB.2.00.1105311020130.5486@localhost6.localdomain6 \
--to=frank.hofmann@tomtom.com \
--cc=linux-arm-kernel@lists.infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox