cache.c 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Cache management functions for Hexagon
  4. *
  5. * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
  6. */
  7. #include <linux/mm.h>
  8. #include <asm/cacheflush.h>
  9. #include <asm/hexagon_vm.h>
  10. #define spanlines(start, end) \
  11. (((end - (start & ~(LINESIZE - 1))) >> LINEBITS) + 1)
  12. void flush_dcache_range(unsigned long start, unsigned long end)
  13. {
  14. unsigned long lines = spanlines(start, end-1);
  15. unsigned long i, flags;
  16. start &= ~(LINESIZE - 1);
  17. local_irq_save(flags);
  18. for (i = 0; i < lines; i++) {
  19. __asm__ __volatile__ (
  20. " dccleaninva(%0); "
  21. :
  22. : "r" (start)
  23. );
  24. start += LINESIZE;
  25. }
  26. local_irq_restore(flags);
  27. }
  28. void flush_icache_range(unsigned long start, unsigned long end)
  29. {
  30. unsigned long lines = spanlines(start, end-1);
  31. unsigned long i, flags;
  32. start &= ~(LINESIZE - 1);
  33. local_irq_save(flags);
  34. for (i = 0; i < lines; i++) {
  35. __asm__ __volatile__ (
  36. " dccleana(%0); "
  37. " icinva(%0); "
  38. :
  39. : "r" (start)
  40. );
  41. start += LINESIZE;
  42. }
  43. __asm__ __volatile__ (
  44. "isync"
  45. );
  46. local_irq_restore(flags);
  47. }
  48. EXPORT_SYMBOL(flush_icache_range);
  49. void hexagon_clean_dcache_range(unsigned long start, unsigned long end)
  50. {
  51. unsigned long lines = spanlines(start, end-1);
  52. unsigned long i, flags;
  53. start &= ~(LINESIZE - 1);
  54. local_irq_save(flags);
  55. for (i = 0; i < lines; i++) {
  56. __asm__ __volatile__ (
  57. " dccleana(%0); "
  58. :
  59. : "r" (start)
  60. );
  61. start += LINESIZE;
  62. }
  63. local_irq_restore(flags);
  64. }
  65. void hexagon_inv_dcache_range(unsigned long start, unsigned long end)
  66. {
  67. unsigned long lines = spanlines(start, end-1);
  68. unsigned long i, flags;
  69. start &= ~(LINESIZE - 1);
  70. local_irq_save(flags);
  71. for (i = 0; i < lines; i++) {
  72. __asm__ __volatile__ (
  73. " dcinva(%0); "
  74. :
  75. : "r" (start)
  76. );
  77. start += LINESIZE;
  78. }
  79. local_irq_restore(flags);
  80. }
  81. /*
  82. * This is just really brutal and shouldn't be used anyways,
  83. * especially on V2. Left here just in case.
  84. */
  85. void flush_cache_all_hexagon(void)
  86. {
  87. unsigned long flags;
  88. local_irq_save(flags);
  89. __vmcache_ickill();
  90. __vmcache_dckill();
  91. __vmcache_l2kill();
  92. local_irq_restore(flags);
  93. mb();
  94. }
  95. void copy_to_user_page(struct vm_area_struct *vma, struct page *page,
  96. unsigned long vaddr, void *dst, void *src, int len)
  97. {
  98. memcpy(dst, src, len);
  99. if (vma->vm_flags & VM_EXEC) {
  100. flush_icache_range((unsigned long) dst,
  101. (unsigned long) dst + len);
  102. }
  103. }