X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=arch%2Farm%2Fmm%2Ffault-armv.c;h=5f0a790940ef735b98bfebad5b2c4e5ead60e363;hb=c7b5ebbddf7bcd3651947760f423e3783bbe6573;hp=d03940c1b6970ce9690cccdd9371a4066ec94f31;hpb=a2c21200f1c81b08cb55e417b68150bba439b646;p=linux-2.6.git diff --git a/arch/arm/mm/fault-armv.c b/arch/arm/mm/fault-armv.c index d03940c1b..5f0a79094 100644 --- a/arch/arm/mm/fault-armv.c +++ b/arch/arm/mm/fault-armv.c @@ -76,59 +76,12 @@ no_pmd: return 0; } -static void __flush_dcache_page(struct page *page) -{ - struct address_space *mapping = page_mapping(page); - struct mm_struct *mm = current->active_mm; - struct vm_area_struct *mpnt = NULL; - struct prio_tree_iter iter; - unsigned long offset; - pgoff_t pgoff; - - __cpuc_flush_dcache_page(page_address(page)); - - if (!mapping) - return; - - /* - * With a VIVT cache, we need to also write back - * and invalidate any user data. - */ - pgoff = page->index << (PAGE_CACHE_SHIFT - PAGE_SHIFT); - - flush_dcache_mmap_lock(mapping); - while ((mpnt = vma_prio_tree_next(mpnt, &mapping->i_mmap, - &iter, pgoff, pgoff)) != NULL) { - /* - * If this VMA is not in our MM, we can ignore it. - */ - if (mpnt->vm_mm != mm) - continue; - if (!(mpnt->vm_flags & VM_MAYSHARE)) - continue; - offset = (pgoff - mpnt->vm_pgoff) << PAGE_SHIFT; - flush_cache_page(mpnt, mpnt->vm_start + offset); - } - flush_dcache_mmap_unlock(mapping); -} - -void flush_dcache_page(struct page *page) -{ - struct address_space *mapping = page_mapping(page); - - if (mapping && !mapping_mapped(mapping)) - set_bit(PG_dcache_dirty, &page->flags); - else - __flush_dcache_page(page); -} -EXPORT_SYMBOL(flush_dcache_page); - static void make_coherent(struct vm_area_struct *vma, unsigned long addr, struct page *page, int dirty) { struct address_space *mapping = page_mapping(page); struct mm_struct *mm = vma->vm_mm; - struct vm_area_struct *mpnt = NULL; + struct vm_area_struct *mpnt; struct prio_tree_iter iter; unsigned long offset; pgoff_t pgoff; @@ -145,8 +98,7 @@ make_coherent(struct vm_area_struct *vma, unsigned long addr, struct page *page, * cache coherency. */ flush_dcache_mmap_lock(mapping); - while ((mpnt = vma_prio_tree_next(mpnt, &mapping->i_mmap, - &iter, pgoff, pgoff)) != NULL) { + vma_prio_tree_foreach(mpnt, &iter, &mapping->i_mmap, pgoff, pgoff) { /* * If this VMA is not in our MM, we can ignore it. * Note that we intentionally mask out the VMA @@ -190,10 +142,21 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long addr, pte_t pte) if (page_mapping(page)) { int dirty = test_and_clear_bit(PG_dcache_dirty, &page->flags); - if (dirty) + if (dirty) { + /* + * This is our first userspace mapping of this page. + * Ensure that the physical page is coherent with + * the kernel mapping. + * + * FIXME: only need to do this on VIVT and aliasing + * VIPT cache architectures. We can do that + * by choosing whether to set this bit... + */ __cpuc_flush_dcache_page(page_address(page)); + } - make_coherent(vma, addr, page, dirty); + if (cache_is_vivt()) + make_coherent(vma, addr, page, dirty); } }