mmap.c 1.9 KB

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