ARM: Disable outer cache before kexec call
Subsystems (2)
cover ARM: Disable outer cache before kexec call
The following patch series addresses the problem, that the kexec code does not disable the outer cache before disabling the inner cache and jumping into the new kernel. This results in random crashes of the new kernel.
Thanks,
tglx
PATCH 1/2 arm: Disable outer (L2) cache in kexec
An embedded and charset-unspecified text was scrubbed...
Name: arm-outer-cache-disable-for-kexec.patch
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20100701/1c9ff78e/attachment.ksh>
PATCH 2/2 arm: Implement l2x0 cache disable function
In reply to Thomas GleixnerAn embedded and charset-unspecified text was scrubbed...
Name: arm-l2x0-cache-disable.patch
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20100701/d3d156ab/attachment.ksh>
A message that is not in the archive (sent off-list or not yet received): [email protected]
PATCH 2/2 arm: Implement l2x0 cache disable function
Quoted 18 lines
---------- Forwarded message ----------
From: Thomas Gleixner <[email protected]>
Date: Thu, Jul 1, 2010 at 9:35 PM
Subject: [patch 2/2] arm: Implement l2x0 cache disable function
To: LAK <[email protected]>
Cc: Catalin Marinas <[email protected]>This function is called from kexec code before the inner caches are disabled to prevent random crashes in the new kernel.
Signed-off-by Thomas Gleixner <[email protected]>Index:
linux-2.6/arch/arm/mm/cache-l2x0.c
===================================================================
arch/arm/mm/cache-l2x0.c static void l2x0_flush_range(unsigned lo · line 213
Quoted 8 lines
arch/arm/mm/cache-l2x0.c +5
-0@@ -206,6 +206,12 @@ static void l2x0_flush_range(unsigned lospin_unlock_irqrestore (&l2x0_lock, flags); } +static void l2x0_cache_disable (void ) +{ +l2x0_inv_all (); +writel (0 , l2x0_base +L2X0_CTRL ); +}
I think it's a problem for PL310 controller where the access to L2X0_CTRL is secure, accessing this in non-secure mode will fault.
Srinidhi
PATCH 2/2 arm: Implement l2x0 cache disable function
In reply to Thomas GleixnerQuoted 9 lines · Thomas Gleixner
This function is called from kexec code before the inner caches are disabled to prevent random crashes in the new kernel.
Signed-off-by Thomas Gleixner <[email protected]>Index:
linux-2.6/arch/arm/mm/cache-l2x0.c
===================================================================
arch/arm/mm/cache-l2x0.c static void l2x0_flush_range(unsigned lo · line 213
Quoted 8 lines
arch/arm/mm/cache-l2x0.c +5
-0@@ -206,6 +206,12 @@ static void l2x0_flush_range(unsigned lospin_unlock_irqrestore (&l2x0_lock, flags); } +static void l2x0_cache_disable (void ) +{ +l2x0_inv_all (); +writel (0 , l2x0_base +L2X0_CTRL ); +}
Even if we go this route, we need an l2x0_flush_all() rather than invalidate here as the latter removes dirty cache lines without evicting them first.
Signature · 1 line
Catalin
PATCH 2/2 arm: Implement l2x0 cache disable function
Quoted 13 lines · Catalin Marinas
Quoted 12 lines · Thomas Gleixner
This function is called from kexec code before the inner caches are disabled to prevent random crashes in the new kernel.
Signed-off-by Thomas Gleixner <[email protected]>Index:
linux-2.6/arch/arm/mm/cache-l2x0.c
===================================================================arch/arm/mm/cache-l2x0.c +0
-0@@ -206,6 +206,12 @@ static void l2x0_flush_range(unsigned lospin_unlock_irqrestore (&l2x0_lock, flags); }
Quoted 9 lines
arch/arm/mm/cache-l2x0.c static void l2x0_flush_range(unsigned lo · line 213
Quoted 5 lines
arch/arm/mm/cache-l2x0.c +5
-0+static void l2x0_cache_disable (void ) +{ +l2x0_inv_all (); +writel (0 , l2x0_base +L2X0_CTRL ); +}Even if we go this route, we need an
l2x0_flush_all()rather than invalidate here as the latter removes dirty cache lines without evicting them first.
True, but that's an implementation detail. What's more important is to make a decision how to solve the problem as kexec is completely unusable for all L2 systems right now.
I think the correct way to deal with this is disabling L2 and let the OMAP3 folks deal with it. As Tony said there is some SMI magic to do that, so we can do the following:
In l2x0_init()
if (!l2_enabled()) {
if (non_secure()) {
omap_smi_magic_l2_enable();
outer_cache.disable = omap_smi_magic_l2_disable;
} else {
sane_l2_enable();
outer_cache.disable = sane_l2_disable;
}}
Russells patch has its own merits nevertheless as a cleanup and simplification, but that's a separate issue.
Thoughts ?
tglx
PATCH 2/2 arm: Implement l2x0 cache disable function
Quoted 25 lines · Thomas Gleixner
Quoted 13 lines · Catalin Marinas
Quoted 12 lines · Thomas Gleixner
This function is called from kexec code before the inner caches are disabled to prevent random crashes in the new kernel.
Signed-off-by Thomas Gleixner <[email protected]>Index:
linux-2.6/arch/arm/mm/cache-l2x0.c
===================================================================arch/arm/mm/cache-l2x0.c +0
-0@@ -206,6 +206,12 @@ static void l2x0_flush_range(unsigned lospin_unlock_irqrestore (&l2x0_lock, flags); }Quoted 9 lines
arch/arm/mm/cache-l2x0.c static void l2x0_flush_range(unsigned lo · line 213
Quoted 5 lines
arch/arm/mm/cache-l2x0.c +5
-0+static void l2x0_cache_disable (void ) +{ +l2x0_inv_all (); +writel (0 , l2x0_base +L2X0_CTRL ); +}Even if we go this route, we need an
l2x0_flush_all()rather than invalidate here as the latter removes dirty cache lines without evicting them first.
Quoted 3 lines
True, but that's an implementation detail. What's more important is to make a decision how to solve the problem as kexec is completely unusable for all L2 systems right now.
My view is that we should try to find why cache flushing doesn't work but unfortunately I don't have any spare time to look into this (would need to use tools like ICE debugging/tracing).
Quoted 6 lines
I think the correct way to deal with this is disabling L2 and let the OMAP3 folks deal with it. As Tony said there is some SMI magic to do that, so we can do the following:
In
l2x0_init()
Quoted 9 lines
if (!l2_enabled()) {
if (non_secure()) {
omap_smi_magic_l2_enable();
outer_cache.disable = omap_smi_magic_l2_disable;
} else {
sane_l2_enable();
outer_cache.disable = sane_l2_disable;
}
}The non_secure() bit is the key. AFAIK there isn't an easy way to check whether you are running in secure or non-secure mode (I think there is some CP14 debug register telling this but those registers aren't mandatory in a CPU implementation).
Signature · 1 line
Catalin
PATCH 2/2 arm: Implement l2x0 cache disable function
Quoted 26 lines · Catalin Marinas
Quoted 25 lines · Thomas Gleixner
Quoted 22 lines · Catalin Marinas
Quoted 9 lines · Thomas Gleixner
This function is called from kexec code before the inner caches are disabled to prevent random crashes in the new kernel.
Signed-off-by Thomas Gleixner <[email protected]>Index:
linux-2.6/arch/arm/mm/cache-l2x0.c
===================================================================arch/arm/mm/cache-l2x0.c static void l2x0_flush_range(unsigned lo · line 213
Quoted 8 lines
arch/arm/mm/cache-l2x0.c +5
-0@@ -206,6 +206,12 @@ static void l2x0_flush_range(unsigned lospin_unlock_irqrestore (&l2x0_lock, flags); } +static void l2x0_cache_disable (void ) +{ +l2x0_inv_all (); +writel (0 , l2x0_base +L2X0_CTRL ); +}Even if we go this route, we need an
l2x0_flush_all()rather than invalidate here as the latter removes dirty cache lines without evicting them first.
Quoted 7 lines
Quoted 3 lines
True, but that's an implementation detail. What's more important is to make a decision how to solve the problem as kexec is completely unusable for all L2 systems right now.
My view is that we should try to find why cache flushing doesn't work but unfortunately I don't have any spare time to look into this (would need to use tools like ICE debugging/tracing).
Simply because you need to flush the cache in the decompressor of the new kernel before jumping into it and I doubt that Russell will be happy about adding an utter L2 mess to the decompressor.
Quoted 16 lines
Quoted 6 lines
I think the correct way to deal with this is disabling L2 and let the OMAP3 folks deal with it. As Tony said there is some SMI magic to do that, so we can do the following:
In
l2x0_init()Quoted 9 lines
if (!l2_enabled()) { if (non_secure()) { omap_smi_magic_l2_enable(); outer_cache.disable = omap_smi_magic_l2_disable; } else { sane_l2_enable(); outer_cache.disable = sane_l2_disable; } }
Quoted 4 lines
The
non_secure()bit is the key. AFAIK there isn't an easy way to check whether you are running in secure or non-secure mode (I think there is some CP14 debug register telling this but those registers aren't mandatory in a CPU implementation).
And how does the kernel decide whether it needs to use that SMI code in sleep34xx.S or not ?
Thanks,
tglx
PATCH 2/2 arm: Implement l2x0 cache disable function
Quoted 67 lines
-----Original Message-----
From: linux-arm-kernel-bounces at lists.infradead.org [mailto:linux-arm- kernel-bounces at lists.infradead.org] On Behalf Of Thomas Gleixner
Sent: Friday, July 02, 2010 10:10 PM
To: Catalin Marinas
Cc: Tony Lindgren; LAK
Subject: Re: [patch 2/2] arm: Implement l2x0 cache disable functionQuoted 5 lines · Catalin Marinas
Quoted 4 lines · Thomas Gleixner
Quoted 2 lines · Catalin Marinas
Quoted 1 line · Thomas Gleixner
This function is called from kexec code before the inner caches
are
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
disabled to prevent random crashes in the new kernel.
Signed-off-by Thomas Gleixner <[email protected]>Index:
linux-2.6/arch/arm/mm/cache-l2x0.c===================================================================
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
arch/arm/mm/cache-l2x0.c +0
-0@@ -206,6 +206,12 @@ static void l2x0_flush_range(unsigned lospin_unlock_irqrestore (&l2x0_lock, flags); }Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
arch/arm/mm/cache-l2x0.c static void l2x0_flush_range(unsigned lo · line 213
Quoted 5 lines
arch/arm/mm/cache-l2x0.c +5
-0+static void l2x0_cache_disable (void ) +{ +l2x0_inv_all (); +writel (0 , l2x0_base +L2X0_CTRL ); +}Even if we go this route, we need an
l2x0_flush_all()rather than invalidate here as the latter removes dirty cache lines withoutevicting
Quoted 9 lines
Quoted 5 lines
Quoted 1 line
them first.
True, but that's an implementation detail. What's more important is to make a decision how to solve the problem as kexec is completely unusable for all L2 systems right now.
My view is that we should try to find why cache flushing doesn't work but unfortunately I don't have any spare time to look into this (would need to use tools like ICE debugging/tracing).
Simply because you need to flush the cache in the decompressor of the new kernel before jumping into it and I doubt that Russell will be happy about adding an utter L2 mess to the decompressor.
Quoted 16 lines
Quoted 15 lines
I think the correct way to deal with this is disabling L2 and let the OMAP3 folks deal with it. As Tony said there is some SMI magic to do that, so we can do the following:
In
l2x0_init()if (!l2_enabled()) { if (non_secure()) { omap_smi_magic_l2_enable(); outer_cache.disable = omap_smi_magic_l2_disable; } else { sane_l2_enable(); outer_cache.disable = sane_l2_disable; } }
Quoted 8 lines
Quoted 4 lines
The
non_secure()bit is the key. AFAIK there isn't an easy way to check whether you are running in secure or non-secure mode (I think there is some CP14 debug register telling this but those registers aren't mandatory in a CPU implementation).And how does the kernel decide whether it needs to use that SMI code in
sleep34xx.Sor not ?
It's OMAP3 specific code and SMI is the only way to enable or disable L2.
Regards,
Santosh
PATCH 2/2 arm: Implement l2x0 cache disable function
In reply to Thomas GleixnerQuoted 32 lines · Thomas Gleixner
Quoted 30 lines · Catalin Marinas
Quoted 28 lines · Thomas Gleixner
Quoted 13 lines · Catalin Marinas
Quoted 12 lines · Thomas Gleixner
This function is called from kexec code before the inner caches are disabled to prevent random crashes in the new kernel.
Signed-off-by Thomas Gleixner <[email protected]>Index:
linux-2.6/arch/arm/mm/cache-l2x0.c
===================================================================arch/arm/mm/cache-l2x0.c +0
-0@@ -206,6 +206,12 @@ static void l2x0_flush_range(unsigned lospin_unlock_irqrestore (&l2x0_lock, flags); }Quoted 9 lines
arch/arm/mm/cache-l2x0.c static void l2x0_flush_range(unsigned lo · line 213
Quoted 5 lines
arch/arm/mm/cache-l2x0.c +5
-0+static void l2x0_cache_disable (void ) +{ +l2x0_inv_all (); +writel (0 , l2x0_base +L2X0_CTRL ); +}Even if we go this route, we need an
l2x0_flush_all()rather than invalidate here as the latter removes dirty cache lines without evicting them first.True, but that's an implementation detail. What's more important is to make a decision how to solve the problem as kexec is completely unusable for all L2 systems right now.
Quoted 7 lines
Quoted 3 lines
My view is that we should try to find why cache flushing doesn't work but unfortunately I don't have any spare time to look into this (would need to use tools like ICE debugging/tracing).
Simply because you need to flush the cache in the decompressor of the new kernel before jumping into it and I doubt that Russell will be happy about adding an utter L2 mess to the decompressor.
The decompressor can create mappings as inner cacheable outer non-cacheable and it would not pollute the L2 cache.
I wonder how the OMAP guys deal with an already enabled L2 cache during decompressing.
Quoted 16 lines
Quoted 16 lines
Quoted 15 lines
I think the correct way to deal with this is disabling L2 and let the OMAP3 folks deal with it. As Tony said there is some SMI magic to do that, so we can do the following:
In
l2x0_init()if (!l2_enabled()) { if (non_secure()) { omap_smi_magic_l2_enable(); outer_cache.disable = omap_smi_magic_l2_disable; } else { sane_l2_enable(); outer_cache.disable = sane_l2_disable; } }
Quoted 7 lines
Quoted 4 lines
The
non_secure()bit is the key. AFAIK there isn't an easy way to check whether you are running in secure or non-secure mode (I think there is some CP14 debug register telling this but those registers aren't mandatory in a CPU implementation).And how does the kernel decide whether it needs to use that SMI code in
sleep34xx.Sor not ?
I think that's done at configuration time. But ideally we shouldn't have different configurations for secure and non-secure modes.
Signature · 1 line
Catalin
PATCH 2/2 arm: Implement l2x0 cache disable function
Quoted 7 lines · Catalin Marinas
Quoted 3 lines · Thomas Gleixner
Simply because you need to flush the cache in the decompressor of the new kernel before jumping into it and I doubt that Russell will be happy about adding an utter L2 mess to the decompressor.
The decompressor can create mappings as inner cacheable outer non-cacheable and it would not pollute the L2 cache.
Doesn't solve the problem of boot loaders. Doesn't solve the problem that there may be dirty cache lines left in the L2 cache which could be searched.
There's too many "implementation" possibilities to bite us. The only safe thing to do is to disable the L2 cache.
PATCH 2/2 arm: Implement l2x0 cache disable function
In reply to Catalin MarinasQuoted 53 lines
-----Original Message-----
From: linux-arm-kernel-bounces at lists.infradead.org [mailto:linux-arm- kernel-bounces at lists.infradead.org] On Behalf Of Catalin Marinas
Sent: Friday, July 02, 2010 10:25 PM
To: Thomas Gleixner
Cc: Tony Lindgren; LAK
Subject: Re: [patch 2/2] arm: Implement l2x0 cache disable functionQuoted 7 lines · Thomas Gleixner
Quoted 5 lines · Catalin Marinas
Quoted 4 lines · Thomas Gleixner
Quoted 2 lines · Catalin Marinas
Quoted 1 line · Thomas Gleixner
This function is called from kexec code before the inner caches
are
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
disabled to prevent random crashes in the new kernel.
Signed-off-by Thomas Gleixner <[email protected]>Index:
linux-2.6/arch/arm/mm/cache-l2x0.c===================================================================
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
arch/arm/mm/cache-l2x0.c +0
-0@@ -206,6 +206,12 @@ static void l2x0_flush_range(unsigned lospin_unlock_irqrestore (&l2x0_lock, flags); }Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
arch/arm/mm/cache-l2x0.c static void l2x0_flush_range(unsigned lo · line 213
Quoted 5 lines
arch/arm/mm/cache-l2x0.c +5
-0+static void l2x0_cache_disable (void ) +{ +l2x0_inv_all (); +writel (0 , l2x0_base +L2X0_CTRL ); +}Even if we go this route, we need an
l2x0_flush_all()rather than invalidate here as the latter removes dirty cache lines withoutevicting
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 1 line
them first.
True, but that's an implementation detail. What's more important is
to
Quoted 10 lines
Quoted 6 lines
Quoted 2 lines
make a decision how to solve the problem as kexec is completely unusable for all L2 systems right now.
My view is that we should try to find why cache flushing doesn't work but unfortunately I don't have any spare time to look into this (would need to use tools like ICE debugging/tracing).
Simply because you need to flush the cache in the decompressor of the new kernel before jumping into it and I doubt that Russell will be happy about adding an utter L2 mess to the decompressor.
Quoted 5 lines
The decompressor can create mappings as inner cacheable outer non-cacheable and it would not pollute the L2 cache.
I wonder how the OMAP guys deal with an already enabled L2 cache during decompressing.
$L2 isn't enabled during the decompression. It's done " __v7_setup" on OMAP3 and just before " l2x0_init" on OMAP4
PATCH 2/2 arm: Implement l2x0 cache disable function
Quoted 12 lines · Santosh
Quoted 12 lines
From: linux-arm-kernel-bounces at lists.infradead.org [mailto:linux-arm- kernel-bounces at lists.infradead.org] On Behalf Of Catalin Marinas
Quoted 8 lines · Thomas Gleixner
Quoted 3 lines · Catalin Marinas
My view is that we should try to find why cache flushing doesn't work but unfortunately I don't have any spare time to look into this (would need to use tools like ICE debugging/tracing).
Simply because you need to flush the cache in the decompressor of the new kernel before jumping into it and I doubt that Russell will be happy about adding an utter L2 mess to the decompressor.
Quoted 8 lines
Quoted 5 lines
The decompressor can create mappings as inner cacheable outer non-cacheable and it would not pollute the L2 cache.
I wonder how the OMAP guys deal with an already enabled L2 cache during decompressing.
$L2 isn't enabled during the decompression. It's done "
__v7_setup" on OMAP3 and just before "l2x0_init" on OMAP4
Another approach would have been to mark the page tables as outer non-cacheable in the decompressor.
Anyway, if you already handle L2 cache initialisation during __v7_setup (and we could go back to a thread where I asked for per-platform CPU initialisation support), you could handle L2 cache disabling as well.
As per Thomas' patches, the outer_cache_fns structure has a .disable() function and this can be overridden by the OMAP code after l2x0_init().
The only additional comment I have to Thomas' second patch is that the l2x0_cache_disable() implementation has to flush (clean+inv) the L2 cache (rather than just invalidate) and then disable by writing the L2 control register. The L2 flushing function doesn't need to be exported via outer_cache_fns since it's only the disabling that would handle it.
Signature · 1 line
Catalin
PATCH 2/2 arm: Implement l2x0 cache disable function
Quoted 32 lines
-----Original Message-----
From: Catalin Marinas [mailto:catalin.marinas at arm.com]
Sent: Sunday, July 04, 2010 7:37 PM
To: Shilimkar, Santosh
Cc: Thomas Gleixner; Tony Lindgren; LAK
Subject: RE: [patch 2/2] arm: Implement l2x0 cache disable functionQuoted 5 lines · Santosh
Quoted 5 lines
From: linux-arm-kernel-bounces at lists.infradead.org [mailto:linux-arm- kernel-bounces at lists.infradead.org] On Behalf Of Catalin Marinas
Quoted 2 lines · Thomas Gleixner
Quoted 1 line · Catalin Marinas
My view is that we should try to find why cache flushing doesn't
work
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
but unfortunately I don't have any spare time to look into this
(would
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 1 line
need to use tools like ICE debugging/tracing).
Simply because you need to flush the cache in the decompressor of
the
Quoted 7 lines
Quoted 7 lines
Quoted 2 lines
new kernel before jumping into it and I doubt that Russell will be happy about adding an utter L2 mess to the decompressor.
The decompressor can create mappings as inner cacheable outer non-cacheable and it would not pollute the L2 cache.
I wonder how the OMAP guys deal with an already enabled L2 cache
during
Quoted 3 lines
Quoted 1 line
decompressing.
$L2 isn't enabled during the decompression. It's done "
__v7_setup" onOMAP3
Quoted 9 lines
Quoted 1 line
and just before "
l2x0_init" on OMAP4Another approach would have been to mark the page tables as outer non-cacheable in the decompressor.
Anyway, if you already handle L2 cache initialisation during
__v7_setup(and we could go back to a thread where I asked for per-platform CPU initialisation support), you could handle L2 cache disabling as well.
Such a hook would be really nice. We have been discussing this for some time.
Quoted 3 lines
As per Thomas' patches, the
outer_cache_fnsstructure has a .disable() function and this can be overridden by the OMAP code afterl2x0_init().
Yes. That's good idea.
Quoted 6 lines
The only additional comment I have to Thomas' second patch is that the
l2x0_cache_disable()implementation has to flush (clean+inv) the L2 cache (rather than just invalidate) and then disable by writing the L2 control register. The L2 flushing function doesn't need to be exported viaouter_cache_fnssince it's only the disabling that would handle it.
Exporting a l2x0_flush_all would be good as well if it's not a problem.
Regards,
Santosh
PATCH 2/2 arm: Implement l2x0 cache disable function
In reply to Shilimkar, SantoshQuoted 13 lines · Santosh
Quoted 13 lines
-----Original Message-----
From: linux-arm-kernel-bounces at lists.infradead.org [mailto:linux-arm- kernel-bounces at lists.infradead.org] On Behalf Of Catalin Marinas
Sent: Friday, July 02, 2010 10:25 PM
To: Thomas Gleixner
Cc: Tony Lindgren; LAK
Subject: Re: [patch 2/2] arm: Implement l2x0 cache disable functionQuoted 3 lines · Thomas Gleixner
Simply because you need to flush the cache in the decompressor of the new kernel before jumping into it and I doubt that Russell will be happy about adding an utter L2 mess to the decompressor.
Quoted 8 lines
Quoted 5 lines
The decompressor can create mappings as inner cacheable outer non-cacheable and it would not pollute the L2 cache.
I wonder how the OMAP guys deal with an already enabled L2 cache during decompressing.
$L2 isn't enabled during the decompression. It's done "
__v7_setup" on OMAP3 and just before "l2x0_init" on OMAP4
Not on the initial kernel, but on subsequent kernels booted via kexec, because of this issue, L2 will be enabled.
So when the decompressor comes to set up its own page tables - it uses the non-XP format - it ends up with tables setup with C=B=1, which is interpreted as fully cacheable. As the L2 unit is still enabled, this causes the region to be cacheable at L2 as well as L1 - which is not what the decompressor expects.
The result is that cache lines get loaded into L2, and marked dirty. When the decompressor then turns off the cache in order to call the kernel, things go awol because the dirty lines in L2 haven't been flushed out.
I think it's overkill to add L2 support to the decompressor - and I also think it's overkill to teach the decompressor about the XP format tables, especially as the booting documents clearly state that caches shall be disabled before calling the kernel. Also, we really can't insist that this is the case for boot loaders, and then do something different when we call the next kernel.
Also consider the case where the kernel you're booting into doesn't have L2 support enabled - maybe you disabled L2 support because it's causing problems. If you boot with L2 already enabled, then this kernel is going to struggle because it can't handle the enabled L2.
As I've already said, the boot loader case won't expect to be called via its reset vector with L2 enabled either - and could well go wrong if this is done.
So, all the ways you look at it, having L2 enabled when you're exiting the kernel to call some other piece of code (such as boot loader or decompressor) is asking for trouble.
Let's ensure that we bring L2 to a clean and disabled state prior to invoking a boot loader or subsequent kernel - even if that means we have to make SMC calls to achieve that.
PATCH 2/2 arm: Implement l2x0 cache disable function
Quoted 22 lines · Russell King - ARM Linux
Quoted 21 lines · Santosh
Quoted 13 lines
-----Original Message-----
From: linux-arm-kernel-bounces at lists.infradead.org [mailto:linux-arm- kernel-bounces at lists.infradead.org] On Behalf Of Catalin Marinas
Sent: Friday, July 02, 2010 10:25 PM
To: Thomas Gleixner
Cc: Tony Lindgren; LAK
Subject: Re: [patch 2/2] arm: Implement l2x0 cache disable functionQuoted 3 lines · Thomas Gleixner
Simply because you need to flush the cache in the decompressor of the new kernel before jumping into it and I doubt that Russell will be happy about adding an utter L2 mess to the decompressor.
Quoted 5 lines
The decompressor can create mappings as inner cacheable outer non-cacheable and it would not pollute the L2 cache.
I wonder how the OMAP guys deal with an already enabled L2 cache during decompressing.
$L2 isn't enabled during the decompression. It's done "
__v7_setup" on OMAP3 and just before "l2x0_init" on OMAP4
[...]
Quoted 3 lines
I think it's overkill to add L2 support to the decompressor - and I also think it's overkill to teach the decompressor about the XP format tables,
Even if we did this, the secure software needs to be aware of OS rebooting since it may have a non-secure cacheable mapping which is speculatively fetched (and I was also told that the L2 treats the secure access bit as an address one - so you get separate cache lines for secure and non-secure).
Quoted 4 lines
Also consider the case where the kernel you're booting into doesn't have L2 support enabled - maybe you disabled L2 support because it's causing problems. If you boot with L2 already enabled, then this kernel is going to struggle because it can't handle the enabled L2.
You could have an outer non-cacheable cache policy and set the page table bits accordingly. But I agree with you, it's not worth the extra effort.
Quoted 3 lines
Let's ensure that we bring L2 to a clean and disabled state prior to invoking a boot loader or subsequent kernel - even if that means we have to make SMC calls to achieve that.
So Thomas' original patches are pretty much OK, with the exception of using clean+invalidate instead of just invalidate during disabling.
An additional question - do we need to flush the L2 cache again after it was disabled, just in case we got some speculative loads?
Signature · 1 line
Catalin
PATCH 2/2 arm: Implement l2x0 cache disable function
In reply to Catalin MarinasQuoted 8 lines · Catalin Marinas
Quoted 3 lines · Thomas Gleixner
True, but that's an implementation detail. What's more important is to make a decision how to solve the problem as kexec is completely unusable for all L2 systems right now.
My view is that we should try to find why cache flushing doesn't work but unfortunately I don't have any spare time to look into this (would need to use tools like ICE debugging/tracing).
It's quite simple. If you leave the L2 cache enabled, then the decompressor needs to have L2 cache support in it, since it re-enables the cache. We really don't want to go down that route.
Moreover, boot loaders will not expect L2 cache to be enabled when we re-enter them for soft-reboot via their reset vector.
So, I agree with Thomas - we have to preserve the already stated requirements in the kernel booting document(s) which stipulate that caches must be disabled when the kernel is called.
PATCH 2/2 arm: Implement l2x0 cache disable function
In reply to Thomas GleixnerQuoted 33 lines
-----Original Message-----
From: linux-arm-kernel-bounces at lists.infradead.org [mailto:linux-arm- kernel-bounces at lists.infradead.org] On Behalf Of Thomas Gleixner
Sent: Friday, July 02, 2010 9:00 PM
To: Catalin Marinas
Cc: Tony Lindgren; LAK
Subject: Re: [patch 2/2] arm: Implement l2x0 cache disable functionQuoted 13 lines · Catalin Marinas
Quoted 12 lines · Thomas Gleixner
This function is called from kexec code before the inner caches are disabled to prevent random crashes in the new kernel.
Signed-off-by Thomas Gleixner <[email protected]>Index:
linux-2.6/arch/arm/mm/cache-l2x0.c
===================================================================arch/arm/mm/cache-l2x0.c +0
-0@@ -206,6 +206,12 @@ static void l2x0_flush_range(unsigned lospin_unlock_irqrestore (&l2x0_lock, flags); }Quoted 9 lines
arch/arm/mm/cache-l2x0.c static void l2x0_flush_range(unsigned lo · line 213
Quoted 5 lines
arch/arm/mm/cache-l2x0.c +5
-0+static void l2x0_cache_disable (void ) +{ +l2x0_inv_all (); +writel (0 , l2x0_base +L2X0_CTRL ); +}Even if we go this route, we need an
l2x0_flush_all()rather than invalidate here as the latter removes dirty cache lines without evicting them first.
Quoted 8 lines
True, but that's an implementation detail. What's more important is to make a decision how to solve the problem as kexec is completely unusable for all L2 systems right now.
I think the correct way to deal with this is disabling L2 and let the OMAP3 folks deal with it. As Tony said there is some SMI magic to do that, so we can do the following:
Just to be clear OMAP3 don't have external(outer) L2 so the below point is actually applicable to OMAP4. If " omap_smi_magic_l2_enable" such a generic "secure_l2x_enable" hook which
can be populated by the archs should take care of OMAP problem
Quoted 23 lines
In
l2x0_init()if (!l2_enabled()) { if (non_secure()) { omap_smi_magic_l2_enable(); outer_cache.disable = omap_smi_magic_l2_disable; } else { sane_l2_enable(); outer_cache.disable = sane_l2_disable; } }Russells patch has its own merits nevertheless as a cleanup and simplification, but that's a separate issue.
Thoughts ?
tglx
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel at lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
cover ARM: Disable outer cache before kexec call
In reply to Thomas GleixnerHi Thomas,
Quoted 4 lines · Thomas Gleixner
The following patch series addresses the problem, that the kexec code does not disable the outer cache before disabling the inner cache and jumping into the new kernel. This results in random crashes of the new kernel.
We may need other ways to work around this problem. There are platforms like OMAP3 (I think) where the L2 cache cannot be disabled as Linux is running in non-secure (normal) mode.
Cannot some extra cache flushing work around this problem?
Signature · 1 line
Catalin
cover ARM: Disable outer cache before kexec call
Catalin,
Quoted 10 lines · Catalin Marinas
Quoted 4 lines · Thomas Gleixner
The following patch series addresses the problem, that the kexec code does not disable the outer cache before disabling the inner cache and jumping into the new kernel. This results in random crashes of the new kernel.
We may need other ways to work around this problem. There are platforms like OMAP3 (I think) where the L2 cache cannot be disabled as Linux is running in non-secure (normal) mode.
But it can disable the inner caches? That's weird.
Quoted 1 line
Cannot some extra cache flushing work around this problem?
We tried to keep the L2 on and just doing the l2x0_inv_all() call and it hangs.
Thanks,
tglx
cover ARM: Disable outer cache before kexec call
Quoted 7 lines · Thomas Gleixner
Quoted 6 lines · Catalin Marinas
Quoted 4 lines · Thomas Gleixner
The following patch series addresses the problem, that the kexec code does not disable the outer cache before disabling the inner cache and jumping into the new kernel. This results in random crashes of the new kernel.
Quoted 5 lines
Quoted 3 lines
We may need other ways to work around this problem. There are platforms like OMAP3 (I think) where the L2 cache cannot be disabled as Linux is running in non-secure (normal) mode.
But it can disable the inner caches? That's weird.
That's because the CP15 SCTLR register is a banked one, so independent configuration for secure and normal worlds.
The outer cache controller doesn't have banked registers and I'm not even sure it has a notion of secure or non-secure cache line.
Quoted 4 lines
Quoted 1 line
Cannot some extra cache flushing work around this problem?
We tried to keep the L2 on and just doing the
l2x0_inv_all()call and it hangs.
You would probably need an l2x0_flush_all() function which does clean +invalidate. If you only do invalidate you may just remove valid cache lines that have reached the RAM.
We only use the l2x0_inv_all() prior to enabling the L2 cache.
Signature · 1 line
Catalin
cover ARM: Disable outer cache before kexec call
Catalin,
Quoted 12 lines · Catalin Marinas
Quoted 11 lines · Thomas Gleixner
Quoted 9 lines · Catalin Marinas
Quoted 4 lines · Thomas Gleixner
The following patch series addresses the problem, that the kexec code does not disable the outer cache before disabling the inner cache and jumping into the new kernel. This results in random crashes of the new kernel.
We may need other ways to work around this problem. There are platforms like OMAP3 (I think) where the L2 cache cannot be disabled as Linux is running in non-secure (normal) mode.
Quoted 7 lines
Quoted 1 line
But it can disable the inner caches? That's weird.
That's because the CP15 SCTLR register is a banked one, so independent configuration for secure and normal worlds.
The outer cache controller doesn't have banked registers and I'm not even sure it has a notion of secure or non-secure cache line.
Brilliant design.
Quoted 8 lines
Quoted 4 lines
Quoted 1 line
Cannot some extra cache flushing work around this problem?
We tried to keep the L2 on and just doing the
l2x0_inv_all()call and it hangs.You would probably need an
l2x0_flush_all()function which does clean +invalidate. If you only do invalidate you may just remove valid cache lines that have reached the RAM.
Tried that, no fun.
Thanks,
tglx
cover ARM: Disable outer cache before kexec call
Quoted 16 lines · Thomas Gleixner
Quoted 14 lines · Catalin Marinas
Quoted 12 lines · Thomas Gleixner
Quoted 9 lines · Catalin Marinas
Quoted 4 lines · Thomas Gleixner
The following patch series addresses the problem, that the kexec code does not disable the outer cache before disabling the inner cache and jumping into the new kernel. This results in random crashes of the new kernel.
We may need other ways to work around this problem. There are platforms like OMAP3 (I think) where the L2 cache cannot be disabled as Linux is running in non-secure (normal) mode.
But it can disable the inner caches? That's weird.
Quoted 7 lines
Quoted 5 lines
That's because the CP15 SCTLR register is a banked one, so independent configuration for secure and normal worlds.
The outer cache controller doesn't have banked registers and I'm not even sure it has a notion of secure or non-secure cache line.
Brilliant design.
The L2 cache is in many time some device outside the CPU. But in this case I think it's more of a secure software issue - it could simply mark all the secure page tables as outer non-cacheable and just let the normal world handle the L2 cache as it likes.
Quoted 10 lines
Quoted 8 lines
Quoted 4 lines
Quoted 1 line
Cannot some extra cache flushing work around this problem?
We tried to keep the L2 on and just doing the
l2x0_inv_all()call and it hangs.You would probably need an
l2x0_flush_all()function which does clean +invalidate. If you only do invalidate you may just remove valid cache lines that have reached the RAM.Tried that, no fun.
Possibly some ordering issues. Please see Russell's reply on the cache flushing steps (I haven't tried them though).
Signature · 1 line
Catalin
cover ARM: Disable outer cache before kexec call
In reply to Thomas GleixnerQuoted 18 lines · Thomas Gleixner
Catalin,
Quoted 14 lines · Catalin Marinas
Quoted 12 lines · Thomas Gleixner
Quoted 9 lines · Catalin Marinas
Quoted 4 lines · Thomas Gleixner
The following patch series addresses the problem, that the kexec code does not disable the outer cache before disabling the inner cache and jumping into the new kernel. This results in random crashes of the new kernel.
We may need other ways to work around this problem. There are platforms like OMAP3 (I think) where the L2 cache cannot be disabled as Linux is running in non-secure (normal) mode.
But it can disable the inner caches? That's weird.
Quoted 7 lines
Quoted 5 lines
That's because the CP15 SCTLR register is a banked one, so independent configuration for secure and normal worlds.
The outer cache controller doesn't have banked registers and I'm not even sure it has a notion of secure or non-secure cache line.
Brilliant design.
FYI, on secure omaps disabling/enabling/configuring of L2 cache must be done via SMI that runs some function in the secure software (PPA).. The code is there in arch/arm/mach-omap2/sleep34xx.S, just search for SMI or PPA.
Trying to set things via the ARM aux ctrl register will hang the system, so we need to figure out some way to select the L2 enable/disable based on if we're running in secure mode or not.
Regards,
Tony
cover ARM: Disable outer cache before kexec call
In reply to Thomas GleixnerQuoted 18 lines
-----Original Message-----
From: linux-arm-kernel-bounces at lists.infradead.org [mailto:linux-arm- kernel-bounces at lists.infradead.org] On Behalf Of Thomas Gleixner
Sent: Thursday, July 01, 2010 9:59 PM
To: Catalin Marinas
Cc: LAK
Subject: Re: [patch 0/2] ARM: Disable outer cache before kexec callCatalin,
Quoted 7 lines · Catalin Marinas
Quoted 4 lines · Thomas Gleixner
The following patch series addresses the problem, that the kexec code does not disable the outer cache before disabling the inner cache and jumping into the new kernel. This results in random crashes of the new kernel.
Quoted 6 lines
Quoted 3 lines
We may need other ways to work around this problem. There are platforms like OMAP3 (I think) where the L2 cache cannot be disabled as Linux is running in non-secure (normal) mode.
But it can disable the inner caches? That's weird.
If the C bit is disabled then it is as good as L1 and L2 are disabled.
Quoted 5 lines
Quoted 1 line
Cannot some extra cache flushing work around this problem?
We tried to keep the L2 on and just doing the
l2x0_inv_all()call and it hangs.
Regards,
Santosh
cover ARM: Disable outer cache before kexec call
Quoted 18 lines · Santosh
Quoted 18 lines
-----Original Message-----
From: linux-arm-kernel-bounces at lists.infradead.org [mailto:linux-arm- kernel-bounces at lists.infradead.org] On Behalf Of Thomas Gleixner
Sent: Thursday, July 01, 2010 9:59 PM
To: Catalin Marinas
Cc: LAK
Subject: Re: [patch 0/2] ARM: Disable outer cache before kexec callCatalin,
Quoted 7 lines · Catalin Marinas
Quoted 4 lines · Thomas Gleixner
The following patch series addresses the problem, that the kexec code does not disable the outer cache before disabling the inner cache and jumping into the new kernel. This results in random crashes of the new kernel.
Quoted 7 lines
Quoted 5 lines
Quoted 3 lines
We may need other ways to work around this problem. There are platforms like OMAP3 (I think) where the L2 cache cannot be disabled as Linux is running in non-secure (normal) mode.
But it can disable the inner caches? That's weird.
If the C bit is disabled then it is as good as L1 and L2 are disabled.
You may want to disable the I bit in SCTLR as well. With MMU disabled I think the D side acts as strongly ordered (uncached) but you can still get cached fetches in the I-cache (needs some TRM checking though). If that's the case, the L2 cache could see I-cache L1 fetches as cacheable accesses since L2 is a unified cache.
Signature · 1 line
Catalin
cover ARM: Disable outer cache before kexec call
Quoted 37 lines
-----Original Message-----
From: Catalin Marinas [mailto:catalin.marinas at arm.com]
Sent: Thursday, July 01, 2010 10:11 PM
To: Shilimkar, Santosh
Cc: Thomas Gleixner; LAK
Subject: RE: [patch 0/2] ARM: Disable outer cache before kexec callQuoted 8 lines · Santosh
Quoted 8 lines
-----Original Message-----
From: linux-arm-kernel-bounces at lists.infradead.org [mailto:linux-arm- kernel-bounces at lists.infradead.org] On Behalf Of Thomas Gleixner
Sent: Thursday, July 01, 2010 9:59 PM
To: Catalin Marinas
Cc: LAK
Subject: Re: [patch 0/2] ARM: Disable outer cache before kexec callQuoted 6 lines
Quoted 6 lines
Catalin,
Quoted 3 lines · Catalin Marinas
Quoted 1 line · Thomas Gleixner
The following patch series addresses the problem, that the kexec
code
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
does not disable the outer cache before disabling the inner cache
and
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
jumping into the new kernel. This results in random crashes of the
new
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 1 line
kernel.
We may need other ways to work around this problem. There are
platforms
Quoted 1 line
Quoted 1 line
Quoted 1 line
like OMAP3 (I think) where the L2 cache cannot be disabled as Linux
is
Quoted 4 lines
Quoted 3 lines
Quoted 1 line
running in non-secure (normal) mode.
But it can disable the inner caches? That's weird.
Quoted 8 lines
Quoted 1 line
If the C bit is disabled then it is as good as L1 and L2 are disabled.
You may want to disable the I bit in SCTLR as well. With MMU disabled I think the D side acts as strongly ordered (uncached) but you can still get cached fetches in the I-cache (needs some TRM checking though). If that's the case, the L2 cache could see I-cache L1 fetches as cacheable accesses since L2 is a unified cache.
You are right.
Regards,
Santosh
cover ARM: Disable outer cache before kexec call
In reply to Shilimkar, SantoshQuoted 11 lines · Santosh
Quoted 10 lines
-----Original Message-----
From: linux-arm-kernel-bounces at lists.infradead.org [mailto:linux-arm- kernel-bounces at lists.infradead.org] On Behalf Of Thomas Gleixner
To: Catalin Marinas
Cc: LAKCatalin,
But it can disable the inner caches? That's weird.
If the C bit is disabled then it is as good as L1 and L2 are disabled.
However, if L2 contains valid cache lines which haven't been written back, the result of disabling the C bit effectively is instantaneous memory corruption.
We know that some L2 caches aren't searched if the C bit in the MMU tables is disabled, and for those caches I'd imagine the same thing happens when you clear the C bit in the SCTLR when turning off the MMU. What we currently do for L1 is:
- disable interrupts
- clean all caches (optionally invalidating)
- turn off I & C bits
- invalidate all caches
The 'clean' is there to push dirty data out of the caches back into memory. We then turn off the I & C bits, ensuring that no new cache lines are read in. At this point, some caches are no longer searched.
We then invalidate all caches to ensure that when _something_ later re-enables the caches, that they don't see our stale data.
As L2 needs this same handling, what I propose is, for both machine_restart() and machine_kexec():
1. we move the IRQ (and FIQ) disable out of each CPUs proc_fin()
2. call flush_cache_all() immediately after IRQs are disabled (removing any cache flushing from proc_fin() implementations.)
3. call outer_flush_all() (new function) after that
4. call proc_fin() to disable the C & I bits.
5. call flush_cache_all() again to invalidate the inner caches
6. call outer_flush_all() again to invalidate the outer caches
7. whatever's next after the existing cpu_proc_fin()...
The only potential problem I see with this is that (5) and (6) may end up writing back some dirty data associated with the stack, and one of these functions may overwrite its return address - thereby causing us to loop back to (2) or (3). I don't think that's a problem as the next time around this 'loop' we won't be creating new dirty cache lines, and we should get to step 7.
cover ARM: Disable outer cache before kexec call
Quoted 46 lines · Russell King - ARM Linux
Quoted 11 lines · Santosh
Quoted 10 lines
-----Original Message-----
From: linux-arm-kernel-bounces at lists.infradead.org [mailto:linux-arm- kernel-bounces at lists.infradead.org] On Behalf Of Thomas Gleixner
To: Catalin Marinas
Cc: LAKCatalin,
But it can disable the inner caches? That's weird.
If the C bit is disabled then it is as good as L1 and L2 are disabled.
However, if L2 contains valid cache lines which haven't been written back, the result of disabling the C bit effectively is instantaneous memory corruption.
We know that some L2 caches aren't searched if the C bit in the MMU tables is disabled, and for those caches I'd imagine the same thing happens when you clear the C bit in the SCTLR when turning off the MMU. What we currently do for L1 is:
- disable interrupts
- clean all caches (optionally invalidating)
- turn off I & C bits
- invalidate all cachesThe 'clean' is there to push dirty data out of the caches back into memory. We then turn off the I & C bits, ensuring that no new cache lines are read in. At this point, some caches are no longer searched.
We then invalidate all caches to ensure that when _something_ later re-enables the caches, that they don't see our stale data.
As L2 needs this same handling, what I propose is, for both
machine_restart()andmachine_kexec():1. we move the IRQ (and FIQ) disable out of each CPUs
proc_fin()
2. callflush_cache_all()immediately after IRQs are disabled (removing any cache flushing fromproc_fin()implementations.)
3. callouter_flush_all()(new function) after that
4. callproc_fin()to disable the C & I bits.
5. callflush_cache_all()again to invalidate the inner caches
6. callouter_flush_all()again to invalidate the outer caches
7. whatever's next after the existingcpu_proc_fin()...
Quoted 6 lines
The only potential problem I see with this is that (5) and (6) may end up writing back some dirty data associated with the stack, and one of these functions may overwrite its return address - thereby causing us to loop back to (2) or (3). I don't think that's a problem as the next time around this 'loop' we won't be creating new dirty cache lines, and we should get to step 7.
Right, something like this. I've not made an effort to fix the L2 bits, but I have marked the places where attention is required. The interesting bit is the first two files.
The next question this provokes is whether we need a dsb() between steps 3 and 4, and maybe again between 4 and 5, and possibly after 6 ?
arch/arm/kernel/machine_kexec.c | 8 +++++++- arch/arm/kernel/process.c | 20 ++++++++++++++++---- arch/arm/mm/proc-arm1020.S | 6 +----- arch/arm/mm/proc-arm1020e.S | 6 +----- arch/arm/mm/proc-arm1022.S | 6 +----- arch/arm/mm/proc-arm1026.S | 6 +----- arch/arm/mm/proc-arm6_7.S | 2 -- arch/arm/mm/proc-arm720.S | 6 +----- arch/arm/mm/proc-arm740.S | 6 +----- arch/arm/mm/proc-arm7tdmi.S | 2 -- arch/arm/mm/proc-arm920.S | 10 +--------- arch/arm/mm/proc-arm922.S | 10 +--------- arch/arm/mm/proc-arm925.S | 6 +----- arch/arm/mm/proc-arm926.S | 6 +----- arch/arm/mm/proc-arm940.S | 6 +----- arch/arm/mm/proc-arm946.S | 6 +----- arch/arm/mm/proc-arm9tdmi.S | 2 -- arch/arm/mm/proc-fa526.S | 6 +----- arch/arm/mm/proc-feroceon.S | 8 ++------ arch/arm/mm/proc-mohawk.S | 6 +----- arch/arm/mm/proc-sa110.S | 8 ++------ arch/arm/mm/proc-sa1100.S | 6 +----- arch/arm/mm/proc-v6.S | 5 +---- arch/arm/mm/proc-v7.S | 5 +---- arch/arm/mm/proc-xsc3.S | 6 +----- arch/arm/mm/proc-xscale.S | 6 +----- 26 files changed, 46 insertions(+), 124 deletions(-)
arch/arm/kernel/machine_kexec.c +7 -1
@@ -74,7 +74,13 @@ void machine_kexec(struct kimage *image) (unsigned long) reboot_code_buffer + KEXEC_CONTROL_PAGE_SIZE);printk (KERN_INFO "Bye!\n" ); -cpu_proc_fin (); +local_irq_disable (); +local_fiq_disable ();setup_mm_for_reboot (0 );/* mode is not used, so just pass 0*/ +flush_cache_all (); +/* XXX: L2 cache flush */ +cpu_proc_fin (); +flush_cache_all (); +/* XXX: L2 cache flush */ cpu_reset (reboot_code_buffer_phys); }
arch/arm/kernel/process.c +16 -4
@@ -84,10 +84,9 @@ __setup("hlt", hlt_setup);void arm_machine_restart (char mode,const char *cmd) { -/* -* Clean and disable cache, and turn off interrupts -*/ -cpu_proc_fin (); +/* Disable interrupts first */ +local_irq_disable (); +local_fiq_disable ();/* * Tell the mm system that we are going to reboot -
@@ -96,6 +95,19 @@ void arm_machine_restart(char mode, const char *cmd)*/ setup_mm_for_reboot (mode); +/* Clean and invalidate caches */ +flush_cache_all (); + +/* XXX: L2 cache flush */ + +/* Turn off caching */ +cpu_proc_fin (); + +/* Push out any further dirty data, and ensure cache is empty */ +flush_cache_all (); + +/* XXX: L2 cache flush */ +/* * Now call the architecture specific reboot code. */
arch/arm/mm/proc-arm1020.S +1 -5
@@ -79,15 +79,11 @@ ENTRY(cpu_arm1020_proc_init) * cpu_arm1020_proc_fin() */ ENTRY(cpu_arm1020_proc_fin) - stmfd sp!, {lr} - mov ip, #PSR_F_BIT | PSR_I_BIT | SVC_MODE - msr cpsr_c, ip - bl arm1020_flush_kern_cache_all mrc p15, 0, r0, c1, c0, 0 @ ctrl register bic r0, r0, #0x1000 @ ...i............ bic r0, r0, #0x000e @ ............wca. mcr p15, 0, r0, c1, c0, 0 @ disable caches - ldmfd sp!, {pc} + mov pc, lr /* * cpu_arm1020_reset(loc)
arch/arm/mm/proc-arm1020e.S +1 -5
@@ -79,15 +79,11 @@ ENTRY(cpu_arm1020e_proc_init) * cpu_arm1020e_proc_fin() */ ENTRY(cpu_arm1020e_proc_fin) - stmfd sp!, {lr} - mov ip, #PSR_F_BIT | PSR_I_BIT | SVC_MODE - msr cpsr_c, ip - bl arm1020e_flush_kern_cache_all mrc p15, 0, r0, c1, c0, 0 @ ctrl register bic r0, r0, #0x1000 @ ...i............ bic r0, r0, #0x000e @ ............wca. mcr p15, 0, r0, c1, c0, 0 @ disable caches - ldmfd sp!, {pc} + mov pc, lr /* * cpu_arm1020e_reset(loc)
arch/arm/mm/proc-arm1022.S +1 -5
@@ -68,15 +68,11 @@ ENTRY(cpu_arm1022_proc_init) * cpu_arm1022_proc_fin() */ ENTRY(cpu_arm1022_proc_fin) - stmfd sp!, {lr} - mov ip, #PSR_F_BIT | PSR_I_BIT | SVC_MODE - msr cpsr_c, ip - bl arm1022_flush_kern_cache_all mrc p15, 0, r0, c1, c0, 0 @ ctrl register bic r0, r0, #0x1000 @ ...i............ bic r0, r0, #0x000e @ ............wca. mcr p15, 0, r0, c1, c0, 0 @ disable caches - ldmfd sp!, {pc} + mov pc, lr /* * cpu_arm1022_reset(loc)
arch/arm/mm/proc-arm1026.S +1 -5
@@ -68,15 +68,11 @@ ENTRY(cpu_arm1026_proc_init) * cpu_arm1026_proc_fin() */ ENTRY(cpu_arm1026_proc_fin) - stmfd sp!, {lr} - mov ip, #PSR_F_BIT | PSR_I_BIT | SVC_MODE - msr cpsr_c, ip - bl arm1026_flush_kern_cache_all mrc p15, 0, r0, c1, c0, 0 @ ctrl register bic r0, r0, #0x1000 @ ...i............ bic r0, r0, #0x000e @ ............wca. mcr p15, 0, r0, c1, c0, 0 @ disable caches - ldmfd sp!, {pc} + mov pc, lr /* * cpu_arm1026_reset(loc)
arch/arm/mm/proc-arm6_7.S +0 -2
@@ -184,8 +184,6 @@ ENTRY(cpu_arm7_proc_init) ENTRY(cpu_arm6_proc_fin) ENTRY(cpu_arm7_proc_fin) - mov r0, #PSR_F_BIT | PSR_I_BIT | SVC_MODE - msr cpsr_c, r0 mov r0, #0x31 @ ....S..DP...M mcr p15, 0, r0, c1, c0, 0 @ disable caches mov pc, lr
arch/arm/mm/proc-arm720.S +1 -5
@@ -54,15 +54,11 @@ ENTRY(cpu_arm720_proc_init) mov pc, lr ENTRY(cpu_arm720_proc_fin) - stmfd sp!, {lr} - mov ip, #PSR_F_BIT | PSR_I_BIT | SVC_MODE - msr cpsr_c, ip mrc p15, 0, r0, c1, c0, 0 bic r0, r0, #0x1000 @ ...i............ bic r0, r0, #0x000e @ ............wca. mcr p15, 0, r0, c1, c0, 0 @ disable caches - mcr p15, 0, r1, c7, c7, 0 @ invalidate cache - ldmfd sp!, {pc} + mov pc, lr /* * Function: arm720_proc_do_idle(void)
arch/arm/mm/proc-arm740.S +1 -5
@@ -36,15 +36,11 @@ ENTRY(cpu_arm740_switch_mm) * cpu_arm740_proc_fin() */ ENTRY(cpu_arm740_proc_fin) - stmfd sp!, {lr} - mov ip, #PSR_F_BIT | PSR_I_BIT | SVC_MODE - msr cpsr_c, ip mrc p15, 0, r0, c1, c0, 0 bic r0, r0, #0x3f000000 @ bank/f/lock/s bic r0, r0, #0x0000000c @ w-buffer/cache mcr p15, 0, r0, c1, c0, 0 @ disable caches - mcr p15, 0, r0, c7, c0, 0 @ invalidate cache - ldmfd sp!, {pc} + mov pc, lr /* * cpu_arm740_reset(loc)
arch/arm/mm/proc-arm7tdmi.S +0 -2
@@ -36,8 +36,6 @@ ENTRY(cpu_arm7tdmi_switch_mm) * cpu_arm7tdmi_proc_fin() */ ENTRY(cpu_arm7tdmi_proc_fin) - mov r0, #PSR_F_BIT | PSR_I_BIT | SVC_MODE - msr cpsr_c, r0 mov pc, lr /*
arch/arm/mm/proc-arm920.S +1 -9
@@ -69,19 +69,11 @@ ENTRY(cpu_arm920_proc_init) * cpu_arm920_proc_fin() */ ENTRY(cpu_arm920_proc_fin) - stmfd sp!, {lr} - mov ip, #PSR_F_BIT | PSR_I_BIT | SVC_MODE - msr cpsr_c, ip -#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH - bl arm920_flush_kern_cache_all -#else - bl v4wt_flush_kern_cache_all -#endif mrc p15, 0, r0, c1, c0, 0 @ ctrl register bic r0, r0, #0x1000 @ ...i............ bic r0, r0, #0x000e @ ............wca. mcr p15, 0, r0, c1, c0, 0 @ disable caches - ldmfd sp!, {pc} + mov pc, lr /* * cpu_arm920_reset(loc)
arch/arm/mm/proc-arm922.S +1 -9
@@ -71,19 +71,11 @@ ENTRY(cpu_arm922_proc_init) * cpu_arm922_proc_fin() */ ENTRY(cpu_arm922_proc_fin) - stmfd sp!, {lr} - mov ip, #PSR_F_BIT | PSR_I_BIT | SVC_MODE - msr cpsr_c, ip -#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH - bl arm922_flush_kern_cache_all -#else - bl v4wt_flush_kern_cache_all -#endif mrc p15, 0, r0, c1, c0, 0 @ ctrl register bic r0, r0, #0x1000 @ ...i............ bic r0, r0, #0x000e @ ............wca. mcr p15, 0, r0, c1, c0, 0 @ disable caches - ldmfd sp!, {pc} + mov pc, lr /* * cpu_arm922_reset(loc)
arch/arm/mm/proc-arm925.S +1 -5
@@ -92,15 +92,11 @@ ENTRY(cpu_arm925_proc_init) * cpu_arm925_proc_fin() */ ENTRY(cpu_arm925_proc_fin) - stmfd sp!, {lr} - mov ip, #PSR_F_BIT | PSR_I_BIT | SVC_MODE - msr cpsr_c, ip - bl arm925_flush_kern_cache_all mrc p15, 0, r0, c1, c0, 0 @ ctrl register bic r0, r0, #0x1000 @ ...i............ bic r0, r0, #0x000e @ ............wca. mcr p15, 0, r0, c1, c0, 0 @ disable caches - ldmfd sp!, {pc} + mov pc, lr /* * cpu_arm925_reset(loc)
arch/arm/mm/proc-arm926.S +1 -5
@@ -61,15 +61,11 @@ ENTRY(cpu_arm926_proc_init) * cpu_arm926_proc_fin() */ ENTRY(cpu_arm926_proc_fin) - stmfd sp!, {lr} - mov ip, #PSR_F_BIT | PSR_I_BIT | SVC_MODE - msr cpsr_c, ip - bl arm926_flush_kern_cache_all mrc p15, 0, r0, c1, c0, 0 @ ctrl register bic r0, r0, #0x1000 @ ...i............ bic r0, r0, #0x000e @ ............wca. mcr p15, 0, r0, c1, c0, 0 @ disable caches - ldmfd sp!, {pc} + mov pc, lr /* * cpu_arm926_reset(loc)
arch/arm/mm/proc-arm940.S +1 -5
@@ -37,15 +37,11 @@ ENTRY(cpu_arm940_switch_mm) * cpu_arm940_proc_fin() */ ENTRY(cpu_arm940_proc_fin) - stmfd sp!, {lr} - mov ip, #PSR_F_BIT | PSR_I_BIT | SVC_MODE - msr cpsr_c, ip - bl arm940_flush_kern_cache_all mrc p15, 0, r0, c1, c0, 0 @ ctrl register bic r0, r0, #0x00001000 @ i-cache bic r0, r0, #0x00000004 @ d-cache mcr p15, 0, r0, c1, c0, 0 @ disable caches - ldmfd sp!, {pc} + mov pc, lr /* * cpu_arm940_reset(loc)
arch/arm/mm/proc-arm946.S +1 -5
@@ -44,15 +44,11 @@ ENTRY(cpu_arm946_switch_mm) * cpu_arm946_proc_fin() */ ENTRY(cpu_arm946_proc_fin) - stmfd sp!, {lr} - mov ip, #PSR_F_BIT | PSR_I_BIT | SVC_MODE - msr cpsr_c, ip - bl arm946_flush_kern_cache_all mrc p15, 0, r0, c1, c0, 0 @ ctrl register bic r0, r0, #0x00001000 @ i-cache bic r0, r0, #0x00000004 @ d-cache mcr p15, 0, r0, c1, c0, 0 @ disable caches - ldmfd sp!, {pc} + mov pc, lr /* * cpu_arm946_reset(loc)
arch/arm/mm/proc-arm9tdmi.S +0 -2
@@ -36,8 +36,6 @@ ENTRY(cpu_arm9tdmi_switch_mm) * cpu_arm9tdmi_proc_fin() */ ENTRY(cpu_arm9tdmi_proc_fin) - mov r0, #PSR_F_BIT | PSR_I_BIT | SVC_MODE - msr cpsr_c, r0 mov pc, lr /*
arch/arm/mm/proc-fa526.S +1 -5
@@ -39,17 +39,13 @@ ENTRY(cpu_fa526_proc_init) * cpu_fa526_proc_fin() */ ENTRY(cpu_fa526_proc_fin) - stmfd sp!, {lr} - mov ip, #PSR_F_BIT | PSR_I_BIT | SVC_MODE - msr cpsr_c, ip - bl fa_flush_kern_cache_all mrc p15, 0, r0, c1, c0, 0 @ ctrl register bic r0, r0, #0x1000 @ ...i............ bic r0, r0, #0x000e @ ............wca. mcr p15, 0, r0, c1, c0, 0 @ disable caches nop nop - ldmfd sp!, {pc} + mov pc, lr /* * cpu_fa526_reset(loc)
arch/arm/mm/proc-feroceon.S +2 -6
@@ -75,13 +75,9 @@ ENTRY(cpu_feroceon_proc_init) * cpu_feroceon_proc_fin() */ ENTRY(cpu_feroceon_proc_fin) - stmfd sp!, {lr} - mov ip, #PSR_F_BIT | PSR_I_BIT | SVC_MODE - msr cpsr_c, ip - bl feroceon_flush_kern_cache_all - #if defined(CONFIG_CACHE_FEROCEON_L2) && \ !defined(CONFIG_CACHE_FEROCEON_L2_WRITETHROUGH) + XXX: move me to L2 cache support mov r0, #0 mcr p15, 1, r0, c15, c9, 0 @ clean L2 mcr p15, 0, r0, c7, c10, 4 @ drain WB
@@ -91,7 +87,7 @@ ENTRY(cpu_feroceon_proc_fin) bic r0, r0, #0x1000 @ ...i............ bic r0, r0, #0x000e @ ............wca. mcr p15, 0, r0, c1, c0, 0 @ disable caches - ldmfd sp!, {pc} + mov pc, lr /* * cpu_feroceon_reset(loc)
arch/arm/mm/proc-mohawk.S +1 -5
@@ -51,15 +51,11 @@ ENTRY(cpu_mohawk_proc_init) * cpu_mohawk_proc_fin() */ ENTRY(cpu_mohawk_proc_fin) - stmfd sp!, {lr} - mov ip, #PSR_F_BIT | PSR_I_BIT | SVC_MODE - msr cpsr_c, ip - bl mohawk_flush_kern_cache_all mrc p15, 0, r0, c1, c0, 0 @ ctrl register bic r0, r0, #0x1800 @ ...iz........... bic r0, r0, #0x0006 @ .............ca. mcr p15, 0, r0, c1, c0, 0 @ disable caches - ldmfd sp!, {pc} + mov pc, lr /* * cpu_mohawk_reset(loc)
arch/arm/mm/proc-sa110.S +2 -6
@@ -44,17 +44,13 @@ ENTRY(cpu_sa110_proc_init) * cpu_sa110_proc_fin() */ ENTRY(cpu_sa110_proc_fin) - stmfd sp!, {lr} - mov ip, #PSR_F_BIT | PSR_I_BIT | SVC_MODE - msr cpsr_c, ip - bl v4wb_flush_kern_cache_all @ clean caches -1: mov r0, #0 + mov r0, #0 mcr p15, 0, r0, c15, c2, 2 @ Disable clock switching mrc p15, 0, r0, c1, c0, 0 @ ctrl register bic r0, r0, #0x1000 @ ...i............ bic r0, r0, #0x000e @ ............wca. mcr p15, 0, r0, c1, c0, 0 @ disable caches - ldmfd sp!, {pc} + mov pc, lr /* * cpu_sa110_reset(loc)
arch/arm/mm/proc-sa1100.S +1 -5
@@ -55,16 +55,12 @@ ENTRY(cpu_sa1100_proc_init) * - Clean and turn off caches. */ ENTRY(cpu_sa1100_proc_fin) - stmfd sp!, {lr} - mov ip, #PSR_F_BIT | PSR_I_BIT | SVC_MODE - msr cpsr_c, ip - bl v4wb_flush_kern_cache_all mcr p15, 0, ip, c15, c2, 2 @ Disable clock switching mrc p15, 0, r0, c1, c0, 0 @ ctrl register bic r0, r0, #0x1000 @ ...i............ bic r0, r0, #0x000e @ ............wca. mcr p15, 0, r0, c1, c0, 0 @ disable caches - ldmfd sp!, {pc} + mov pc, lr /* * cpu_sa1100_reset(loc)
arch/arm/mm/proc-v6.S +1 -4
@@ -42,14 +42,11 @@ ENTRY(cpu_v6_proc_init) mov pc, lr ENTRY(cpu_v6_proc_fin) - stmfd sp!, {lr} - cpsid if @ disable interrupts - bl v6_flush_kern_cache_all mrc p15, 0, r0, c1, c0, 0 @ ctrl register bic r0, r0, #0x1000 @ ...i............ bic r0, r0, #0x0006 @ .............ca. mcr p15, 0, r0, c1, c0, 0 @ disable caches - ldmfd sp!, {pc} + mov pc, lr /* * cpu_v6_reset(loc)
arch/arm/mm/proc-v7.S +1 -4
@@ -45,14 +45,11 @@ ENTRY(cpu_v7_proc_init) ENDPROC(cpu_v7_proc_init) ENTRY(cpu_v7_proc_fin) - stmfd sp!, {lr} - cpsid if @ disable interrupts - bl v7_flush_kern_cache_all mrc p15, 0, r0, c1, c0, 0 @ ctrl register bic r0, r0, #0x1000 @ ...i............ bic r0, r0, #0x0006 @ .............ca. mcr p15, 0, r0, c1, c0, 0 @ disable caches - ldmfd sp!, {pc} + mov pc, lr ENDPROC(cpu_v7_proc_fin) /*
arch/arm/mm/proc-xsc3.S +1 -5
@@ -90,15 +90,11 @@ ENTRY(cpu_xsc3_proc_init) * cpu_xsc3_proc_fin() */ ENTRY(cpu_xsc3_proc_fin) - str lr, [sp, #-4]! - mov r0, #PSR_F_BIT|PSR_I_BIT|SVC_MODE - msr cpsr_c, r0 - bl xsc3_flush_kern_cache_all @ clean caches mrc p15, 0, r0, c1, c0, 0 @ ctrl register bic r0, r0, #0x1800 @ ...IZ........... bic r0, r0, #0x0006 @ .............CA. mcr p15, 0, r0, c1, c0, 0 @ disable caches - ldr pc, [sp], #4 + mov pc, lr /* * cpu_xsc3_reset(loc)
arch/arm/mm/proc-xscale.S +1 -5
@@ -124,15 +124,11 @@ ENTRY(cpu_xscale_proc_init) * cpu_xscale_proc_fin() */ ENTRY(cpu_xscale_proc_fin) - str lr, [sp, #-4]! - mov r0, #PSR_F_BIT|PSR_I_BIT|SVC_MODE - msr cpsr_c, r0 - bl xscale_flush_kern_cache_all @ clean caches mrc p15, 0, r0, c1, c0, 0 @ ctrl register bic r0, r0, #0x1800 @ ...IZ........... bic r0, r0, #0x0006 @ .............CA. mcr p15, 0, r0, c1, c0, 0 @ disable caches - ldr pc, [sp], #4 + mov pc, lr /* * cpu_xscale_reset(loc)
cover ARM: Disable outer cache before kexec call
Quoted 54 lines · Russell King - ARM Linux
Quoted 46 lines · Russell King - ARM Linux
Quoted 11 lines · Santosh
Quoted 10 lines
-----Original Message-----
From: linux-arm-kernel-bounces at lists.infradead.org [mailto:linux-arm- kernel-bounces at lists.infradead.org] On Behalf Of Thomas Gleixner
To: Catalin Marinas
Cc: LAKCatalin,
But it can disable the inner caches? That's weird.
If the C bit is disabled then it is as good as L1 and L2 are disabled.
However, if L2 contains valid cache lines which haven't been written back, the result of disabling the C bit effectively is instantaneous memory corruption.
We know that some L2 caches aren't searched if the C bit in the MMU tables is disabled, and for those caches I'd imagine the same thing happens when you clear the C bit in the SCTLR when turning off the MMU. What we currently do for L1 is:
- disable interrupts
- clean all caches (optionally invalidating)
- turn off I & C bits
- invalidate all cachesThe 'clean' is there to push dirty data out of the caches back into memory. We then turn off the I & C bits, ensuring that no new cache lines are read in. At this point, some caches are no longer searched.
We then invalidate all caches to ensure that when _something_ later re-enables the caches, that they don't see our stale data.
As L2 needs this same handling, what I propose is, for both
machine_restart()andmachine_kexec():1. we move the IRQ (and FIQ) disable out of each CPUs
proc_fin()
2. callflush_cache_all()immediately after IRQs are disabled (removing any cache flushing fromproc_fin()implementations.)
3. callouter_flush_all()(new function) after that
4. callproc_fin()to disable the C & I bits.
5. callflush_cache_all()again to invalidate the inner caches
6. callouter_flush_all()again to invalidate the outer caches
7. whatever's next after the existingcpu_proc_fin()...Quoted 6 lines
The only potential problem I see with this is that (5) and (6) may end up writing back some dirty data associated with the stack, and one of these functions may overwrite its return address - thereby causing us to loop back to (2) or (3). I don't think that's a problem as the next time around this 'loop' we won't be creating new dirty cache lines, and we should get to step 7.
Quoted 6 lines
Right, something like this. I've not made an effort to fix the L2 bits, but I have marked the places where attention is required. The interesting bit is the first two files.
The next question this provokes is whether we need a
dsb()between steps 3 and 4, and maybe again between 4 and 5, and possibly after 6 ?
We don't need a dsb() after 3 and 6. The outer_flush_all() function would need to do a cache_sync (which polls a register) since that's a background operation on the L2 cache. DSB doesn't have any effect on the L2 cache.
As for between 4 and 5, we may need an ISB as well (not sure about DSB). It's worth checking the recommended MMU disabling sequences in the ARM ARM (if any).
Signature · 1 line
Catalin
cover ARM: Disable outer cache before kexec call
Quoted 22 lines · Catalin Marinas
Quoted 21 lines · Russell King - ARM Linux
Quoted 9 lines · Russell King - ARM Linux
1. we move the IRQ (and FIQ) disable out of each CPUs
proc_fin()
2. callflush_cache_all()immediately after IRQs are disabled (removing any cache flushing fromproc_fin()implementations.)
3. callouter_flush_all()(new function) after that
4. callproc_fin()to disable the C & I bits.
5. callflush_cache_all()again to invalidate the inner caches
6. callouter_flush_all()again to invalidate the outer caches
7. whatever's next after the existingcpu_proc_fin()...Quoted 6 lines
The only potential problem I see with this is that (5) and (6) may end up writing back some dirty data associated with the stack, and one of these functions may overwrite its return address - thereby causing us to loop back to (2) or (3). I don't think that's a problem as the next time around this 'loop' we won't be creating new dirty cache lines, and we should get to step 7.
Right, something like this. I've not made an effort to fix the L2 bits, but I have marked the places where attention is required. The interesting bit is the first two files.
Quoted 7 lines
Quoted 2 lines
The next question this provokes is whether we need a
dsb()between steps 3 and 4, and maybe again between 4 and 5, and possibly after 6 ?We don't need a
dsb()after 3 and 6. Theouter_flush_all()function would need to do acache_sync(which polls a register) since that's a background operation on the L2 cache. DSB doesn't have any effect on the L2 cache.
Well, that leaves a question about Feroceon:
#if defined(CONFIG_CACHE_FEROCEON_L2) && \
!defined(CONFIG_CACHE_FEROCEON_L2_WRITETHROUGH)
mov r0, #0
mcr p15, 1, r0, c15, c9, 0 @ clean L2
mcr p15, 0, r0, c7, c10, 4 @ drain WB#endif
The question is where to move that (effective) DSB to - I guess it can move to arch/arm/mm/cache-feroceon-l2.c.
cover ARM: Disable outer cache before kexec call
In reply to Russell King - ARM LinuxQuoted 6 lines · Russell King - ARM Linux
Quoted 1 line · Russell King - ARM Linux
On Thu, Jul 01, 2010 at 10:08:37PM +0530, Shilimkar, Santosh wrote:
Right, something like this. I've not made an effort to fix the L2 bits, but I have marked the places where attention is required. The interesting bit is the first two files.
I filled in the L2 bits for l2x0 in the following way:
arch/arm/mm/cache-l2x0.c +13 -0
@@ -103,6 +103,18 @@ static void l2x0_cache_sync(void)spin_unlock_irqrestore (&l2x0_lock, flags); } +static inline void l2x0_flush_all (void ) +{ +unsigned long flags; + +/* invalidate all ways */ +spin_lock_irqsave (&l2x0_lock, flags); +writel (l2x0_way_mask, l2x0_base +L2X0_CLEAN_INV_WAY ); +cache_wait (l2x0_base +L2X0_CLEAN_INV_WAY , l2x0_way_mask); +cache_sync (); +spin_unlock_irqrestore (&l2x0_lock, flags); +} +static inline void l2x0_inv_all (void ) {unsigned long flags;
@@ -262,6 +274,7 @@ void __init l2x0_init(void __iomem *base outer_cache.clean_range = l2x0_clean_range; outer_cache.flush_range = l2x0_flush_range; outer_cache.sync = l2x0_cache_sync; + outer_cache.flush_all = l2x0_cache_disable;printk (KERN_INFO "%s cache controller enabled\n" , type); printk(KERN_INFO "l2x0: %d ways, CACHE_ID 0x%08x, AUX_CTRL 0x%08x\n",
Now I added outer_flush_all() calls to the places Russell pointed out.
Unfortunately that works just 5 times in a row, then the box stops dead _after_ the decompressor jumps into the kernel. With current mainline we fail in the decompressor itself. I guess we need the same magic in the decompressor as well.
Adding the L2 disable function on top of these patches works like a charm.
Seriously I think that keeping L2 enabled has enough unknown side effects which might be dealt with by some random cache flushes, but that's not a real solution to the underlying problem.
As a matter of sanity I think we should add the L2 disable functionality. It's logical and it _DOES_ work. Further it solves a real world problem as kexec is broken on any L2 enabled system AFAICT.
The sillyness of OMAP3 can be dealt with by those who invented that insanity w/o imposing their wreckage on everyone.
Thanks,
tglx