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/mm.h>
  17
  18#include <asm/cacheflush.h>
  19
  20#define COLOUR_ALIGN(addr, pgoff)                       \
  21        ((((addr) + SHMLBA - 1) & ~(SHMLBA - 1)) +      \
  22         (((pgoff) << PAGE_SHIFT) & (SHMLBA - 1)))
  23
  24/*
  25 * Ensure that shared mappings are correctly aligned to
  26 * avoid aliasing issues with VIPT caches.
  27 * We need to ensure that
  28 * a specific page of an object is always mapped at a multiple of
  29 * SHMLBA bytes.
  30 */
  31unsigned long
  32arch_get_unmapped_area(struct file *filp, unsigned long addr,
  33                unsigned long len, unsigned long pgoff, unsigned long flags)
  34{
  35        struct mm_struct *mm = current->mm;
  36        struct vm_area_struct *vma;
  37        int do_align = 0;
  38        int aliasing = cache_is_vipt_aliasing();
  39        struct vm_unmapped_area_info info;
  40
  41        /*
  42         * We only need to do colour alignment if D cache aliases.
  43         */
  44        if (aliasing)
  45                do_align = filp || (flags & MAP_SHARED);
  46
  47        /*
  48         * We enforce the MAP_FIXED case.
  49         */
  50        if (flags & MAP_FIXED) {
  51                if (aliasing && flags & MAP_SHARED &&
  52                    (addr - (pgoff << PAGE_SHIFT)) & (SHMLBA - 1))
  53                        return -EINVAL;
  54                return addr;
  55        }
  56
  57        if (len > TASK_SIZE)
  58                return -ENOMEM;
  59
  60        if (addr) {
  61                if (do_align)
  62                        addr = COLOUR_ALIGN(addr, pgoff);
  63                else
  64                        addr = PAGE_ALIGN(addr);
  65
  66                vma = find_vma(mm, addr);
  67                if (TASK_SIZE - len >= addr &&
  68                    (!vma || addr + len <= vm_start_gap(vma)))
  69                        return addr;
  70        }
  71
  72        info.flags = 0;
  73        info.length = len;
  74        info.low_limit = mm->mmap_base;
  75        info.high_limit = TASK_SIZE;
  76        info.align_mask = do_align ? (PAGE_MASK & (SHMLBA - 1)) : 0;
  77        info.align_offset = pgoff << PAGE_SHIFT;
  78        return vm_unmapped_area(&info);
  79}
  80