mmap.c 1.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. // SPDX-License-Identifier: GPL-2.0
  2. // Copyright (C) 2005-2017 Andes Technology Corporation
  3. #include <linux/sched.h>
  4. #include <linux/mman.h>
  5. #include <linux/shm.h>
  6. #define COLOUR_ALIGN(addr,pgoff) \
  7. ((((addr)+SHMLBA-1)&~(SHMLBA-1)) + \
  8. (((pgoff)<<PAGE_SHIFT) & (SHMLBA-1)))
  9. /*
  10. * We need to ensure that shared mappings are correctly aligned to
  11. * avoid aliasing issues with VIPT caches. We need to ensure that
  12. * a specific page of an object is always mapped at a multiple of
  13. * SHMLBA bytes.
  14. *
  15. * We unconditionally provide this function for all cases, however
  16. * in the VIVT case, we optimise out the alignment rules.
  17. */
  18. unsigned long
  19. arch_get_unmapped_area(struct file *filp, unsigned long addr,
  20. unsigned long len, unsigned long pgoff,
  21. unsigned long flags)
  22. {
  23. struct mm_struct *mm = current->mm;
  24. struct vm_area_struct *vma;
  25. int do_align = 0;
  26. struct vm_unmapped_area_info info;
  27. int aliasing = 0;
  28. if(IS_ENABLED(CONFIG_CPU_CACHE_ALIASING))
  29. aliasing = 1;
  30. /*
  31. * We only need to do colour alignment if either the I or D
  32. * caches alias.
  33. */
  34. if (aliasing)
  35. do_align = filp || (flags & MAP_SHARED);
  36. /*
  37. * We enforce the MAP_FIXED case.
  38. */
  39. if (flags & MAP_FIXED) {
  40. if (aliasing && flags & MAP_SHARED &&
  41. (addr - (pgoff << PAGE_SHIFT)) & (SHMLBA - 1))
  42. return -EINVAL;
  43. return addr;
  44. }
  45. if (len > TASK_SIZE)
  46. return -ENOMEM;
  47. if (addr) {
  48. if (do_align)
  49. addr = COLOUR_ALIGN(addr, pgoff);
  50. else
  51. addr = PAGE_ALIGN(addr);
  52. vma = find_vma(mm, addr);
  53. if (TASK_SIZE - len >= addr &&
  54. (!vma || addr + len <= vma->vm_start))
  55. return addr;
  56. }
  57. info.flags = 0;
  58. info.length = len;
  59. info.low_limit = mm->mmap_base;
  60. info.high_limit = TASK_SIZE;
  61. info.align_mask = do_align ? (PAGE_MASK & (SHMLBA - 1)) : 0;
  62. info.align_offset = pgoff << PAGE_SHIFT;
  63. return vm_unmapped_area(&info);
  64. }