mirror of
https://github.com/NixOS/nixpkgs.git
synced 2024-12-15 10:12:58 +00:00
52 lines
1.7 KiB
Diff
52 lines
1.7 KiB
Diff
|
--- 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();
|