- if (pmd_none(*pmd))
- return;
- ptep = pte_offset_map(pmd, address);
- offset = address & ~PMD_MASK;
- if (offset + size > PMD_SIZE)
- size = PMD_SIZE - offset;
- size &= PAGE_MASK;
- for (offset = 0; offset < size; ptep++, offset += PAGE_SIZE) {
- pte_t pte = *ptep;
-
- if (pte_none(pte))
- continue;
-
- if (pte_present(pte) && pte_dirty(pte)) {
- struct page *page;
- unsigned long pgaddr, uaddr;
- unsigned long pfn = pte_pfn(pte);
-
- if (!pfn_valid(pfn))
- continue;
- page = pfn_to_page(pfn);
- if (PageReserved(page) || !page_mapping(page))
- continue;
- pgaddr = (unsigned long) page_address(page);
- uaddr = address + offset;
- if ((pgaddr ^ uaddr) & (1 << 13))
- flush_dcache_page_all(mm, page);
- }
- }
- pte_unmap(ptep - 1);
-}
-
-static inline void flush_cache_pmd_range(struct mm_struct *mm, pgd_t *dir, unsigned long address, unsigned long size)
-{
- pmd_t *pmd;
- unsigned long end;
-
- if (pgd_none(*dir))
- return;
- pmd = pmd_offset(dir, address);
- end = address + size;
- if (end > ((address + PGDIR_SIZE) & PGDIR_MASK))
- end = ((address + PGDIR_SIZE) & PGDIR_MASK);
- do {
- flush_cache_pte_range(mm, pmd, address, end - address);
- address = (address + PMD_SIZE) & PMD_MASK;
- pmd++;
- } while (address < end);
-}
-
-void flush_cache_range(struct vm_area_struct *vma, unsigned long start, unsigned long end)
-{
- struct mm_struct *mm = vma->vm_mm;
- pgd_t *dir = pgd_offset(mm, start);
-
- if (mm == current->mm)
- flushw_user();
-
- if (vma->vm_file == NULL ||
- ((vma->vm_flags & (VM_SHARED|VM_WRITE)) != (VM_SHARED|VM_WRITE)))
- return;
-
- do {
- flush_cache_pmd_range(mm, dir, start, end - start);
- start = (start + PGDIR_SIZE) & PGDIR_MASK;
- dir++;
- } while (start && (start < end));