about summary refs log tree commit diff
path: root/nixpkgs/pkgs/development/compilers/llvm/aarch64.patch
diff options
context:
space:
mode:
Diffstat (limited to 'nixpkgs/pkgs/development/compilers/llvm/aarch64.patch')
-rw-r--r--nixpkgs/pkgs/development/compilers/llvm/aarch64.patch51
1 files changed, 51 insertions, 0 deletions
diff --git a/nixpkgs/pkgs/development/compilers/llvm/aarch64.patch b/nixpkgs/pkgs/development/compilers/llvm/aarch64.patch
new file mode 100644
index 000000000000..205074e48e4e
--- /dev/null
+++ b/nixpkgs/pkgs/development/compilers/llvm/aarch64.patch
@@ -0,0 +1,51 @@
+--- lib/Support/Unix/Memory.inc
++++ lib/Support/Unix/Memory.inc
+@@ -126,8 +126,12 @@
+   Result.Address = Addr;
+   Result.Size = NumPages*PageSize;
+ 
+-  if (PFlags & MF_EXEC)
+-    Memory::InvalidateInstructionCache(Result.Address, Result.Size);
++  // Rely on protectMappedMemory to invalidate instruction cache.
++  if (PFlags & MF_EXEC) {
++    EC = Memory::protectMappedMemory (Result, PFlags);
++    if (EC != std::error_code())
++      return MemoryBlock();
++  }
+ 
+   return Result;
+ }
+@@ -156,15 +160,31 @@
+     return std::error_code(EINVAL, std::generic_category());
+ 
+   int Protect = getPosixProtectionFlags(Flags);
+-
+   uintptr_t Start = alignAddr((uint8_t *)M.Address - PageSize + 1, PageSize);
+   uintptr_t End = alignAddr((uint8_t *)M.Address + M.Size, PageSize);
++
++  bool InvalidateCache = (Flags & MF_EXEC);
++
++#if defined(__arm__) || defined(__aarch64__)
++  // Certain ARM implementations treat icache clear instruction as a memory read,
++  // and CPU segfaults on trying to clear cache on !PROT_READ page.  Therefore we need
++  // to temporarily add PROT_READ for the sake of flushing the instruction caches.
++  if (InvalidateCache && !(Protect & PROT_READ)) {
++    int Result = ::mprotect((void *)Start, End - Start, Protect | PROT_READ);
++    if (Result != 0)
++      return std::error_code(errno, std::generic_category());
++
++    Memory::InvalidateInstructionCache(M.Address, M.Size);
++    InvalidateCache = false;
++  }
++#endif
++
+   int Result = ::mprotect((void *)Start, End - Start, Protect);
+ 
+   if (Result != 0)
+     return std::error_code(errno, std::generic_category());
+ 
+-  if (Flags & MF_EXEC)
++  if (InvalidateCache)
+     Memory::InvalidateInstructionCache(M.Address, M.Size);
+ 
+   return std::error_code();