[ARM] 5366/1: fix shared memory coherency with VIVT L1 + L2 caches
When there are multiple L1-aliasing userland mappings of the same physical page, we currently remap each of them uncached, to prevent VIVT cache aliasing issues. (E.g. writes to one of the mappings not being immediately visible via another mapping.) However, when we do this remapping, there could still be stale data in the L2 cache, and an uncached mapping might bypass L2 and go straight to RAM. This would cause reads from such mappings to see old data (until the dirty L2 line is eventually evicted.) This issue is solved by forcing a L2 cache flush whenever the shared page is made L1 uncacheable. Ideally, we would make L1 uncacheable and L2 cacheable as L2 is PIPT. But Feroceon does not support that combination, and the TEX=5 C=0 B=0 encoding for XSc3 doesn't appear to work in practice. Signed-off-by: Nicolas Pitre <nico@marvell.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
This commit is contained in:
parent
ecbab71c52
commit
08e445bd6a
1 changed files with 4 additions and 1 deletions
|
@ -66,7 +66,10 @@ static int adjust_pte(struct vm_area_struct *vma, unsigned long address)
|
|||
* fault (ie, is old), we can safely ignore any issues.
|
||||
*/
|
||||
if (ret && (pte_val(entry) & L_PTE_MT_MASK) != shared_pte_mask) {
|
||||
flush_cache_page(vma, address, pte_pfn(entry));
|
||||
unsigned long pfn = pte_pfn(entry);
|
||||
flush_cache_page(vma, address, pfn);
|
||||
outer_flush_range((pfn << PAGE_SHIFT),
|
||||
(pfn << PAGE_SHIFT) + PAGE_SIZE);
|
||||
pte_val(entry) &= ~L_PTE_MT_MASK;
|
||||
pte_val(entry) |= shared_pte_mask;
|
||||
set_pte_at(vma->vm_mm, address, pte, entry);
|
||||
|
|
Loading…
Reference in a new issue