aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarcelo Tosatti <marcelo.tosatti@cyclades.com>2005-06-27 13:09:00 -0300
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-06-27 15:11:42 -0700
commitbb1657468152c5e5232c7bf35cf0e9c41b5d9910 (patch)
treebf07dd8c83127551ecd03f116538e5d94ea77593
parentd4b3a80e399c989028acd5185c792fab82eda035 (diff)
downloadkernel_samsung_smdk4412-bb1657468152c5e5232c7bf35cf0e9c41b5d9910.zip
kernel_samsung_smdk4412-bb1657468152c5e5232c7bf35cf0e9c41b5d9910.tar.gz
kernel_samsung_smdk4412-bb1657468152c5e5232c7bf35cf0e9c41b5d9910.tar.bz2
[PATCH] 8xx: avoid "dcbst" misbehaviour with unpopulated TLB
The proposed _tlbie call at update_mmu_cache() is safe because: Addresses for which update_mmu_cache() gets invocated are never inside the static kernel virtual mapping, meaning that there is no risk for the _tlbie() here to be thrashing the pinned entry, as Dan suspected. The intermediate TLB state in which this bug can be triggered is not visible by userspace or any other contexts, except the page fault handling path. So there is no need to worry about userspace dcbxxx users. The other solution to this is to avoid dcbst misbehaviour in the first place, which involves changing in-kernel "dcbst" callers to use 8xx specific SPR's. Summary: On 8xx, cache control instructions (particularly "dcbst" from flush_dcache_icache) fault as write operation if there is an unpopulated TLB entry for the address in question. To workaround that, we invalidate the TLB here, thus avoiding dcbst misbehaviour. Signed-off-by: Marcelo Tosatti <marcelo.tosatti@cyclades.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--arch/ppc/mm/init.c14
1 files changed, 12 insertions, 2 deletions
diff --git a/arch/ppc/mm/init.c b/arch/ppc/mm/init.c
index 334ef41..6164a2b 100644
--- a/arch/ppc/mm/init.c
+++ b/arch/ppc/mm/init.c
@@ -606,9 +606,19 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long address,
struct page *page = pfn_to_page(pfn);
if (!PageReserved(page)
&& !test_bit(PG_arch_1, &page->flags)) {
- if (vma->vm_mm == current->active_mm)
+ if (vma->vm_mm == current->active_mm) {
+#ifdef CONFIG_8xx
+ /* On 8xx, cache control instructions (particularly
+ * "dcbst" from flush_dcache_icache) fault as write
+ * operation if there is an unpopulated TLB entry
+ * for the address in question. To workaround that,
+ * we invalidate the TLB here, thus avoiding dcbst
+ * misbehaviour.
+ */
+ _tlbie(address);
+#endif
__flush_dcache_icache((void *) address);
- else
+ } else
flush_dcache_icache_page(page);
set_bit(PG_arch_1, &page->flags);
}