linux/arch/arc/mm/mmap.c
<<
>>
Prefs
   1/*
   2 * ARC700 mmap
   3 *
   4 * (started from arm version - for VIPT alias handling)
   5 *
   6 * Copyright (C) 2013 Synopsys, Inc. (www.synopsys.com)
   7 *
   8 * This program is free software; you can redistribute it and/or modify
   9 * it under the terms of the GNU General Public License version 2 as
  10 * published by the Free Software Foundation.
  11 */
  12
  13#include <linux/fs.h>
  14#include <linux/mm.h>
  15#include <linux/mman.h>
  16#include <linux/sched.h>
  17#include <asm/cacheflush.h>
  18
  19#define COLOUR_ALIGN(addr, pgoff)                       \
  20        ((((addr) + SHMLBA - 1) & ~(SHMLBA - 1)) +      \
  21         (((pgoff) << PAGE_SHIFT) & (SHMLBA - 1)))
  22
  23/*
  24 * Ensure that shared mappings are correctly aligned to
  25 * avoid aliasing issues with VIPT caches.
  26 * We need to ensure that
  27 * a specific page of an object is always mapped at a multiple of
  28 * SHMLBA bytes.
  29 */
  30unsigned long
  31arch_get_unmapped_area(struct file *filp, unsigned long addr,
  32                unsigned long len, unsigned long pgoff, unsigned long flags)
  33{
  34        struct mm_struct *mm = current->mm;
  35        struct vm_area_struct *vma;
  36        int do_align = 0;
  37        int aliasing = cache_is_vipt_aliasing();
  38        struct vm_unmapped_area_info info;
  39
  40        /*
  41         * We only need to do colour alignment if D cache aliases.
  42         */
  43        if (aliasing)
  44                do_align = filp || (flags & MAP_SHARED);
  45
  46        /*
  47         * We enforce the MAP_FIXED case.
  48         */
  49        if (flags & MAP_FIXED) {
  50                if (aliasing && flags & MAP_SHARED &&
  51                    (addr - (pgoff << PAGE_SHIFT)) & (SHMLBA - 1))
  52                        return -EINVAL;
  53                return addr;
  54        }
  55
  56        if (len > TASK_SIZE)
  57                return -ENOMEM;
  58
  59        if (addr) {
  60                if (do_align)
  61                        addr = COLOUR_ALIGN(addr, pgoff);
  62                else
  63                        addr = PAGE_ALIGN(addr);
  64
  65                vma = find_vma(mm, addr);
  66                if (TASK_SIZE - len >= addr &&
  67                    (!vma || addr + len <= vma->vm_start))
  68                        return addr;
  69        }
  70
  71        info.flags = 0;
  72        info.length = len;
  73        info.low_limit = mm->mmap_base;
  74        info.high_limit = TASK_SIZE;
  75        info.align_mask = do_align ? (PAGE_MASK & (SHMLBA - 1)) : 0;
  76        info.align_offset = pgoff << PAGE_SHIFT;
  77        return vm_unmapped_area(&info);
  78}
  79