clear_cache.c 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. /* ===-- clear_cache.c - Implement __clear_cache ---------------------------===
  2. *
  3. * The LLVM Compiler Infrastructure
  4. *
  5. * This file is dual licensed under the MIT and the University of Illinois Open
  6. * Source Licenses. See LICENSE.TXT for details.
  7. *
  8. * ===----------------------------------------------------------------------===
  9. */
  10. #include "int_lib.h"
  11. #if __APPLE__
  12. #include <libkern/OSCacheControl.h>
  13. #endif
  14. #if defined(__NetBSD__) && defined(__arm__)
  15. #include <machine/sysarch.h>
  16. #endif
  17. #if defined(ANDROID) && defined(__mips__)
  18. #include <sys/cachectl.h>
  19. #endif
  20. #if defined(ANDROID) && defined(__arm__)
  21. #include <asm/unistd.h>
  22. #endif
  23. /*
  24. * The compiler generates calls to __clear_cache() when creating
  25. * trampoline functions on the stack for use with nested functions.
  26. * It is expected to invalidate the instruction cache for the
  27. * specified range.
  28. */
  29. void __clear_cache(void *start, void *end) {
  30. #if __i386__ || __x86_64__
  31. /*
  32. * Intel processors have a unified instruction and data cache
  33. * so there is nothing to do
  34. */
  35. #elif defined(__arm__) && !defined(__APPLE__)
  36. #if defined(__NetBSD__)
  37. struct arm_sync_icache_args arg;
  38. arg.addr = (uintptr_t)start;
  39. arg.len = (uintptr_t)end - (uintptr_t)start;
  40. sysarch(ARM_SYNC_ICACHE, &arg);
  41. #elif defined(ANDROID)
  42. const register int start_reg __asm("r0") = (int) (intptr_t) start;
  43. const register int end_reg __asm("r1") = (int) (intptr_t) end;
  44. const register int flags __asm("r2") = 0;
  45. const register int syscall_nr __asm("r7") = __ARM_NR_cacheflush;
  46. __asm __volatile("svc 0x0" : "=r"(start_reg)
  47. : "r"(syscall_nr), "r"(start_reg), "r"(end_reg), "r"(flags) : "r0");
  48. if (start_reg != 0) {
  49. compilerrt_abort();
  50. }
  51. #else
  52. compilerrt_abort();
  53. #endif
  54. #elif defined(ANDROID) && defined(__mips__)
  55. const uintptr_t start_int = (uintptr_t) start;
  56. const uintptr_t end_int = (uintptr_t) end;
  57. _flush_cache(start, (end_int - start_int), BCACHE);
  58. #elif defined(__aarch64__) && !defined(__APPLE__)
  59. uint64_t xstart = (uint64_t)(uintptr_t) start;
  60. uint64_t xend = (uint64_t)(uintptr_t) end;
  61. // Get Cache Type Info
  62. uint64_t ctr_el0;
  63. __asm __volatile("mrs %0, ctr_el0" : "=r"(ctr_el0));
  64. /*
  65. * dc & ic instructions must use 64bit registers so we don't use
  66. * uintptr_t in case this runs in an IPL32 environment.
  67. */
  68. const size_t dcache_line_size = 4 << ((ctr_el0 >> 16) & 15);
  69. for (uint64_t addr = xstart; addr < xend; addr += dcache_line_size)
  70. __asm __volatile("dc cvau, %0" :: "r"(addr));
  71. __asm __volatile("dsb ish");
  72. const size_t icache_line_size = 4 << ((ctr_el0 >> 0) & 15);
  73. for (uint64_t addr = xstart; addr < xend; addr += icache_line_size)
  74. __asm __volatile("ic ivau, %0" :: "r"(addr));
  75. __asm __volatile("isb sy");
  76. #else
  77. #if __APPLE__
  78. /* On Darwin, sys_icache_invalidate() provides this functionality */
  79. sys_icache_invalidate(start, end-start);
  80. #else
  81. compilerrt_abort();
  82. #endif
  83. #endif
  84. }