[PATCH] ARM: setup_mm_for_reboot(): use flush_cache_louis()
Nicolas Pitre
nicolas.pitre at linaro.org
Wed Nov 7 13:03:40 EST 2012
On Wed, 7 Nov 2012, Will Deacon wrote:
> On Wed, Nov 07, 2012 at 09:56:35AM +0000, Russell King - ARM Linux wrote:
> > On Wed, Nov 07, 2012 at 09:51:06AM +0000, Will Deacon wrote:
> > > Wouldn't the L2 flush in this case be included with the code that turns off
> > > caching? For reboot, that's currently done in __sort_restart -- the cache
> > > flush in setup_mm_for_reboot is just to ensure that the idmap tables are
> > > visible to the hardware walker iirc.
> >
> > Good point - but it does raise another issue. Why do we do this flush and
> > TLB invalidate afterwards in setup_mm_for_reboot() ? It makes sense if
> > we change existing page tables, but we don't anymore, we're just switching
> > them, and cpu_switch_mm() will do whatever's necessary to make the new
> > page tables visible. So I think we can get rid of that flusing in there.
>
> Hmm, I'm not sure about that. Looking at cpu_v7_switch_mm (the 2-level
> version) for example, we set the ASID and then set the new TTBR. There's no
> flushing of page tables like we get in set_pte and no TLB flushing either.
>
> Now, given that the idmap_pgd is populated as an early_initcall, I really
> doubt we need that flush_cache_all but the TLB invalidate is surely
> required?
Why wouldn't cpu_switch_mm() take care of that already if that is
necessary? Hmmm, I suppose the asid of the init task isn't associated
with the idmap in any way, hence the need for flushing the tlbs.
I'd not rely on the early_initcall to assume the new page table is moved
out of the cache though.
What about this alternate patch:
diff --git a/arch/arm/mm/idmap.c b/arch/arm/mm/idmap.c
index ab88ed4f8e..1ab429761c 100644
--- a/arch/arm/mm/idmap.c
+++ b/arch/arm/mm/idmap.c
@@ -92,6 +92,9 @@ static int __init init_static_idmap(void)
(long long)idmap_start, (long long)idmap_end);
identity_mapping_add(idmap_pgd, idmap_start, idmap_end);
+ /* Flush L1 for the hardware to see this page table content */
+ flush_cache_louis();
+
return 0;
}
early_initcall(init_static_idmap);
@@ -103,12 +106,12 @@ early_initcall(init_static_idmap);
*/
void setup_mm_for_reboot(void)
{
- /* Clean and invalidate L1. */
- flush_cache_all();
-
/* Switch to the identity mapping. */
cpu_switch_mm(idmap_pgd, &init_mm);
- /* Flush the TLB. */
+ /*
+ * On ARMv7, the ASID of the init task is not associated with
+ * this mapping. TLBs must be flushed.
+ */
local_flush_tlb_all();
}
More information about the linux-arm-kernel
mailing list