Commit bb165746 authored by Marcelo Tosatti's avatar Marcelo Tosatti Committed by Linus Torvalds

[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: default avatarMarcelo Tosatti <marcelo.tosatti@cyclades.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent d4b3a80e
...@@ -606,9 +606,19 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, ...@@ -606,9 +606,19 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long address,
struct page *page = pfn_to_page(pfn); struct page *page = pfn_to_page(pfn);
if (!PageReserved(page) if (!PageReserved(page)
&& !test_bit(PG_arch_1, &page->flags)) { && !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); __flush_dcache_icache((void *) address);
else } else
flush_dcache_icache_page(page); flush_dcache_icache_page(page);
set_bit(PG_arch_1, &page->flags); set_bit(PG_arch_1, &page->flags);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment