using identity_mapping_add & switching MMU state - how ?

Frank Hofmann frank.hofmann at tomtom.com
Thu Jun 2 12:46:39 EDT 2011


On Thu, 2 Jun 2011, Dave Martin wrote:

> 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

Dave, Will,

thanks for the pointer.

I agree common code to do this sort of transition would be useful, both 
for kexec and hibernation.


The code for cpu_reset() on the _older_ ARM architectures does switch the 
MMU off, but said for v6/v7 isn't mainline (it's discussed in various 
patch submissions, by Per and others, related to kexec over the last 
year).

It seems not to be quite that simple as to add a cpu_reset() which zeroes 
CR_M in the control bits. I'm unsure as to what works and who made it work 
...

Ideally, I'd hope for being able to do the transition like this:

 	/* set up whatever 1:1 mappings are needed - which ones ?! */

 	flush_cache_all();
 	flush_tlb_all();

 	/* flush/disable whatever other caches ... */

 	cpu_proc_fin();				/* i/d cache off */

 	cpu_reset(__pa(target_function));	/* MMU off, jump physical */

which seems pretty much the usecase that machine_kexec() also does.

It just doesn't look like the code is reached.

The only real difference between the hibernation restore and the kexec 
path, seems to be that kexec "reuses" current->mm(->pgd) while hibernation 
restore uses init_mm and a throwaway pagedir; the latter means there's no 
need attempting to save/restore the pmd's overwritten by the identity 
mappings.


FrankH.



More information about the linux-arm-kernel mailing list