mmap.c 1.7 KB

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