From: dave.martin@linaro.org (Dave Martin)
To: linux-arm-kernel@lists.infradead.org
Subject: using identity_mapping_add & switching MMU state - how ?
Date: Thu, 2 Jun 2011 17:22:07 +0100 [thread overview]
Message-ID: <20110602162207.GB2156@arm.com> (raw)
In-Reply-To: <alpine.DEB.2.00.1106021621400.2311@localhost6.localdomain6>
On Thu, Jun 02, 2011 at 04:44:02PM +0100, Frank Hofmann wrote:
> Hi,
>
>
> I'm trying to find a way to do an MMU off / on transition.
>
> What I want to do is to call cpu_do_resume() from the hibernation
> restore codepath.
>
> I've succeeded to make this work by adding a test whether the MMU is
> already on when cpu_resume_mmu() is called.
>
> I'm not sure that sort of thing is proper; hence I've been trying to
> find a way to disable the MMU before calling cpu_do_resume().
>
> Can't seem to get this to work though; even though I'm creating a
> separate MMU context that's given 1:1 mappings for all of kernel
> code/data, execution still hangs as soon as I enable the code
> section below that switches the MMU off.
I think Per Fransson has been working on this area for kexec.
Given the intrinsic scariness of code for turning MMUs off, I think
it would be best if there's a single common implementation which is
usable for hibernation and kexec, and any other code which needs
to do this (CPU hotplug?)
Maybe Per has some ideas on how to do that...
Cheers
---Dave
>
>
> What I have at the moment is code that looks like this:
>
> ==============================================================================
> [ ... ]
> unsigned long notrace __swsusp_arch_restore_image(void)
> {
> extern struct pbe *restore_pblist;
> struct pbe *pbe;
>
> /* __swsusp_pg_dir has been created using pgd_alloc(&init_mm); */
>
> cpu_switch_mm(__swsusp_pg_dir, &init_mm);
>
> for (pbe = restore_pblist; pbe; pbe = pbe->next)
> copy_page(pbe->orig_address, pbe->address);
>
> flush_tlb_all();
> flush_cache_all();
>
> identity_mapping_add(__swsusp_pg_dir, __pa(_stext), __pa(_etext));
> identity_mapping_add(__swsusp_pg_dir, __pa(_sdata), __pa(_edata));
>
> cpu_switch_mm(__swsusp_pg_dir, &init_mm);
>
> flush_tlb_all();
> flush_cache_all();
>
> cpu_proc_fin(); /* turns caches off */
>
> /* caller requires v:p offset to calculate physical addresses */
> return (unsigned long)(PHYS_OFFSET - PAGE_OFFSET);
> }
>
> [ ... ]
> ENTRY(swsusp_arch_resume)
> mov r2, #PSR_I_BIT | PSR_F_BIT | SVC_MODE
> msr cpsr_c, r2
> /*
> * Switch stack to a nosavedata region to make sure image restore
> * doesn't clobber it underneath itself.
> */
> ldr sp, =(__swsusp_resume_stk + PAGE_SIZE / 2)
> bl __swsusp_arch_restore_image
>
> /*
> * Restore the CPU registers.
> */
> mov r1, r0
> ldr r0, =(__swsusp_arch_ctx + (NREGS * 4))
> /*
> * This is what I'm trying to switch off; yet, doing so makes things hang
> */
> #if 0
> ldr r2, =cpu_do_resume
> sub r2, r1 @ __pa()
> ldr r3, =.Lmmu_is_off
> sub r3, r1 @ __pa()
> sub r0, r1 @ __pa()
> ldr lr, =.Lpost_mmu
> mrc p15, 0, r1, c1, c0, 0
> bic r1, #CR_M
> mcr p15, 0, r1, c1, c0, 0 @ MMU OFF
>
> mrc p15, 0, r1, c2, c0, 0 @ queue a dependency on CP15
> sub pc, r3, r1, lsr #32 @ to local label, phys addr
> .ltorg
> .align 5
> .Lmmu_is_off:
> mov pc, r2 @ jump to phys cpu_v6_do_resume
> .Lpost_mmu:
> #else
> bl cpu_do_resume
> #endif
> ldr r0, =__swsusp_arch_ctx
> ldmia r0!, {r1-r11,lr} @ nonvolatile regs
> ldr sp, [r0] @ stack
> msr cpsr, r1
> msr spsr, r2
>
> mov r0, #0
> stmfd sp!, {r0, lr}
> bl cpu_init @ reinitialize other modes
> ldmfd sp!, {r0, pc}
> ENDPROC(swsusp_arch_resume)
> ==============================================================================
>
> I.e. it performs the steps:
>
> - flush all caches, tlbs
> - setup identity mappings for all kernel code & data
> - switch to a self-contained pagedir
> - flush again
> - finish cpu (disable caches)
> - switch MMU off, re-read config reg to force necessary wait,
> and jump to physical address of "self".
>
>
> As said, things work just fine if simply doing the "bl
> cpu_do_resume" and adding a "MMU already on" check to
> cpu_resume_mmu().
>
>
> I must be missing something there; I've been reading the ARM kexec
> postings,
>
> http://lists.infradead.org/pipermail/linux-arm-kernel/2010-July/020183.html
>
> for the basic idea, and used the style from smp.c (alloc a temporary
> pagedir, create identity mappings there). Still, there's something
> not quite right ...
>
>
> Any ideas what I'm missing ?
> Thanks,
>
> FrankH.
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
next prev parent reply other threads:[~2011-06-02 16:22 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-06-02 15:44 using identity_mapping_add & switching MMU state - how ? Frank Hofmann
2011-06-02 16:20 ` Will Deacon
2011-06-02 16:22 ` Dave Martin [this message]
2011-06-02 16:46 ` Frank Hofmann
2011-06-02 18:07 ` Lorenzo Pieralisi
2011-06-03 12:20 ` Frank Hofmann
2011-06-02 20:16 ` Russell King - ARM Linux
2011-06-03 10:44 ` Frank Hofmann
2011-06-03 15:56 ` Frank Hofmann
2011-06-03 23:53 ` Russell King - ARM Linux
2011-06-06 16:32 ` 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=20110602162207.GB2156@arm.com \
--to=dave.martin@linaro.org \
--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 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.