Fix __clear_cache declaration.
[oota-llvm.git] / lib / Support / Unix / Memory.inc
1 //===- Unix/Memory.cpp - Generic UNIX System Configuration ------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file defines some functions for various memory management utilities.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "Unix.h"
15 #include "llvm/Support/DataTypes.h"
16 #include "llvm/Support/ErrorHandling.h"
17 #include "llvm/Support/Process.h"
18
19 #ifdef HAVE_SYS_MMAN_H
20 #include <sys/mman.h>
21 #endif
22
23 #ifdef __APPLE__
24 #include <mach/mach.h>
25 #endif
26
27 #if defined(__mips__)
28 #  if defined(__OpenBSD__)
29 #    include <mips64/sysarch.h>
30 #  else
31 #    include <sys/cachectl.h>
32 #  endif
33 #endif
34
35 extern "C" void sys_icache_invalidate(const void *Addr, size_t len);
36 extern "C" void __clear_cache(void *, void*);
37
38 namespace {
39
40 int getPosixProtectionFlags(unsigned Flags) {
41   switch (Flags) {
42   case llvm::sys::Memory::MF_READ:
43     return PROT_READ;
44   case llvm::sys::Memory::MF_WRITE:
45     return PROT_WRITE;
46   case llvm::sys::Memory::MF_READ|llvm::sys::Memory::MF_WRITE:
47     return PROT_READ | PROT_WRITE;
48   case llvm::sys::Memory::MF_READ|llvm::sys::Memory::MF_EXEC:
49     return PROT_READ | PROT_EXEC;
50   case llvm::sys::Memory::MF_READ |
51          llvm::sys::Memory::MF_WRITE |
52          llvm::sys::Memory::MF_EXEC:
53     return PROT_READ | PROT_WRITE | PROT_EXEC;
54   case llvm::sys::Memory::MF_EXEC:
55 #if defined(__FreeBSD__)
56     // On PowerPC, having an executable page that has no read permission
57     // can have unintended consequences.  The function InvalidateInstruction-
58     // Cache uses instructions dcbf and icbi, both of which are treated by
59     // the processor as loads.  If the page has no read permissions,
60     // executing these instructions will result in a segmentation fault.
61     // Somehow, this problem is not present on Linux, but it does happen
62     // on FreeBSD.
63     return PROT_READ | PROT_EXEC;
64 #else
65     return PROT_EXEC;
66 #endif
67   default:
68     llvm_unreachable("Illegal memory protection flag specified!");
69   }
70   // Provide a default return value as required by some compilers.
71   return PROT_NONE;
72 }
73
74 } // namespace
75
76 namespace llvm {
77 namespace sys {
78
79 MemoryBlock
80 Memory::allocateMappedMemory(size_t NumBytes,
81                              const MemoryBlock *const NearBlock,
82                              unsigned PFlags,
83                              error_code &EC) {
84   EC = error_code::success();
85   if (NumBytes == 0)
86     return MemoryBlock();
87
88   static const size_t PageSize = process::get_self()->page_size();
89   const size_t NumPages = (NumBytes+PageSize-1)/PageSize;
90
91   int fd = -1;
92 #ifdef NEED_DEV_ZERO_FOR_MMAP
93   static int zero_fd = open("/dev/zero", O_RDWR);
94   if (zero_fd == -1) {
95     EC = error_code(errno, system_category());
96     return MemoryBlock();
97   }
98   fd = zero_fd;
99 #endif
100
101   int MMFlags = MAP_PRIVATE |
102 #ifdef HAVE_MMAP_ANONYMOUS
103   MAP_ANONYMOUS
104 #else
105   MAP_ANON
106 #endif
107   ; // Ends statement above
108
109   int Protect = getPosixProtectionFlags(PFlags);
110
111   // Use any near hint and the page size to set a page-aligned starting address
112   uintptr_t Start = NearBlock ? reinterpret_cast<uintptr_t>(NearBlock->base()) +
113                                       NearBlock->size() : 0;
114   if (Start && Start % PageSize)
115     Start += PageSize - Start % PageSize;
116
117   void *Addr = ::mmap(reinterpret_cast<void*>(Start), PageSize*NumPages,
118                       Protect, MMFlags, fd, 0);
119   if (Addr == MAP_FAILED) {
120     if (NearBlock) //Try again without a near hint
121       return allocateMappedMemory(NumBytes, 0, PFlags, EC);
122
123     EC = error_code(errno, system_category());
124     return MemoryBlock();
125   }
126
127   MemoryBlock Result;
128   Result.Address = Addr;
129   Result.Size = NumPages*PageSize;
130
131   if (PFlags & MF_EXEC)
132     Memory::InvalidateInstructionCache(Result.Address, Result.Size);
133
134   return Result;
135 }
136
137 error_code
138 Memory::releaseMappedMemory(MemoryBlock &M) {
139   if (M.Address == 0 || M.Size == 0)
140     return error_code::success();
141
142   if (0 != ::munmap(M.Address, M.Size))
143     return error_code(errno, system_category());
144
145   M.Address = 0;
146   M.Size = 0;
147
148   return error_code::success();
149 }
150
151 error_code
152 Memory::protectMappedMemory(const MemoryBlock &M, unsigned Flags) {
153   if (M.Address == 0 || M.Size == 0)
154     return error_code::success();
155
156   if (!Flags)
157     return error_code(EINVAL, generic_category());
158
159   int Protect = getPosixProtectionFlags(Flags);
160
161   int Result = ::mprotect(M.Address, M.Size, Protect);
162   if (Result != 0)
163     return error_code(errno, system_category());
164
165   if (Flags & MF_EXEC)
166     Memory::InvalidateInstructionCache(M.Address, M.Size);
167
168   return error_code::success();
169 }
170
171 /// AllocateRWX - Allocate a slab of memory with read/write/execute
172 /// permissions.  This is typically used for JIT applications where we want
173 /// to emit code to the memory then jump to it.  Getting this type of memory
174 /// is very OS specific.
175 ///
176 MemoryBlock
177 Memory::AllocateRWX(size_t NumBytes, const MemoryBlock* NearBlock,
178                     std::string *ErrMsg) {
179   if (NumBytes == 0) return MemoryBlock();
180
181   size_t PageSize = process::get_self()->page_size();
182   size_t NumPages = (NumBytes+PageSize-1)/PageSize;
183
184   int fd = -1;
185 #ifdef NEED_DEV_ZERO_FOR_MMAP
186   static int zero_fd = open("/dev/zero", O_RDWR);
187   if (zero_fd == -1) {
188     MakeErrMsg(ErrMsg, "Can't open /dev/zero device");
189     return MemoryBlock();
190   }
191   fd = zero_fd;
192 #endif
193
194   int flags = MAP_PRIVATE |
195 #ifdef HAVE_MMAP_ANONYMOUS
196   MAP_ANONYMOUS
197 #else
198   MAP_ANON
199 #endif
200   ;
201
202   void* start = NearBlock ? (unsigned char*)NearBlock->base() +
203                             NearBlock->size() : 0;
204
205 #if defined(__APPLE__) && defined(__arm__)
206   void *pa = ::mmap(start, PageSize*NumPages, PROT_READ|PROT_EXEC,
207                     flags, fd, 0);
208 #else
209   void *pa = ::mmap(start, PageSize*NumPages, PROT_READ|PROT_WRITE|PROT_EXEC,
210                     flags, fd, 0);
211 #endif
212   if (pa == MAP_FAILED) {
213     if (NearBlock) //Try again without a near hint
214       return AllocateRWX(NumBytes, 0);
215
216     MakeErrMsg(ErrMsg, "Can't allocate RWX Memory");
217     return MemoryBlock();
218   }
219
220 #if defined(__APPLE__) && defined(__arm__)
221   kern_return_t kr = vm_protect(mach_task_self(), (vm_address_t)pa,
222                                 (vm_size_t)(PageSize*NumPages), 0,
223                                 VM_PROT_READ | VM_PROT_EXECUTE | VM_PROT_COPY);
224   if (KERN_SUCCESS != kr) {
225     MakeErrMsg(ErrMsg, "vm_protect max RX failed");
226     return MemoryBlock();
227   }
228
229   kr = vm_protect(mach_task_self(), (vm_address_t)pa,
230                   (vm_size_t)(PageSize*NumPages), 0,
231                   VM_PROT_READ | VM_PROT_WRITE);
232   if (KERN_SUCCESS != kr) {
233     MakeErrMsg(ErrMsg, "vm_protect RW failed");
234     return MemoryBlock();
235   }
236 #endif
237
238   MemoryBlock result;
239   result.Address = pa;
240   result.Size = NumPages*PageSize;
241
242   return result;
243 }
244
245 bool Memory::ReleaseRWX(MemoryBlock &M, std::string *ErrMsg) {
246   if (M.Address == 0 || M.Size == 0) return false;
247   if (0 != ::munmap(M.Address, M.Size))
248     return MakeErrMsg(ErrMsg, "Can't release RWX Memory");
249   return false;
250 }
251
252 bool Memory::setWritable (MemoryBlock &M, std::string *ErrMsg) {
253 #if defined(__APPLE__) && defined(__arm__)
254   if (M.Address == 0 || M.Size == 0) return false;
255   Memory::InvalidateInstructionCache(M.Address, M.Size);
256   kern_return_t kr = vm_protect(mach_task_self(), (vm_address_t)M.Address,
257     (vm_size_t)M.Size, 0, VM_PROT_READ | VM_PROT_WRITE);
258   return KERN_SUCCESS == kr;
259 #else
260   return true;
261 #endif
262 }
263
264 bool Memory::setExecutable (MemoryBlock &M, std::string *ErrMsg) {
265 #if defined(__APPLE__) && defined(__arm__)
266   if (M.Address == 0 || M.Size == 0) return false;
267   Memory::InvalidateInstructionCache(M.Address, M.Size);
268   kern_return_t kr = vm_protect(mach_task_self(), (vm_address_t)M.Address,
269     (vm_size_t)M.Size, 0, VM_PROT_READ | VM_PROT_EXECUTE | VM_PROT_COPY);
270   return KERN_SUCCESS == kr;
271 #else
272   return true;
273 #endif
274 }
275
276 bool Memory::setRangeWritable(const void *Addr, size_t Size) {
277 #if defined(__APPLE__) && defined(__arm__)
278   kern_return_t kr = vm_protect(mach_task_self(), (vm_address_t)Addr,
279                                 (vm_size_t)Size, 0,
280                                 VM_PROT_READ | VM_PROT_WRITE);
281   return KERN_SUCCESS == kr;
282 #else
283   return true;
284 #endif
285 }
286
287 bool Memory::setRangeExecutable(const void *Addr, size_t Size) {
288 #if defined(__APPLE__) && defined(__arm__)
289   kern_return_t kr = vm_protect(mach_task_self(), (vm_address_t)Addr,
290                                 (vm_size_t)Size, 0,
291                                 VM_PROT_READ | VM_PROT_EXECUTE | VM_PROT_COPY);
292   return KERN_SUCCESS == kr;
293 #else
294   return true;
295 #endif
296 }
297
298 /// InvalidateInstructionCache - Before the JIT can run a block of code
299 /// that has been emitted it must invalidate the instruction cache on some
300 /// platforms.
301 void Memory::InvalidateInstructionCache(const void *Addr,
302                                         size_t Len) {
303
304 // icache invalidation for PPC and ARM.
305 #if defined(__APPLE__)
306
307 #  if (defined(__POWERPC__) || defined (__ppc__) || \
308      defined(_POWER) || defined(_ARCH_PPC)) || defined(__arm__)
309   sys_icache_invalidate(const_cast<void *>(Addr), Len);
310 #  endif
311
312 #else
313
314 #  if (defined(__POWERPC__) || defined (__ppc__) || \
315        defined(_POWER) || defined(_ARCH_PPC)) && defined(__GNUC__)
316   const size_t LineSize = 32;
317
318   const intptr_t Mask = ~(LineSize - 1);
319   const intptr_t StartLine = ((intptr_t) Addr) & Mask;
320   const intptr_t EndLine = ((intptr_t) Addr + Len + LineSize - 1) & Mask;
321
322   for (intptr_t Line = StartLine; Line < EndLine; Line += LineSize)
323     asm volatile("dcbf 0, %0" : : "r"(Line));
324   asm volatile("sync");
325
326   for (intptr_t Line = StartLine; Line < EndLine; Line += LineSize)
327     asm volatile("icbi 0, %0" : : "r"(Line));
328   asm volatile("isync");
329 #  elif (defined(__arm__) || defined(__aarch64__)) && defined(__GNUC__)
330   // FIXME: Can we safely always call this for __GNUC__ everywhere?
331   const char *Start = static_cast<const char *>(Addr);
332   const char *End = Start + Len;
333   __clear_cache(const_cast<char *>(Start), const_cast<char *>(End));
334 #  elif defined(__mips__)
335   const char *Start = static_cast<const char *>(Addr);
336 #    if defined(ANDROID)
337   // The declaration of "cacheflush" in Android bionic:
338   // extern int cacheflush(long start, long end, long flags);
339   const char *End = Start + Len;
340   long LStart = reinterpret_cast<long>(const_cast<char *>(Start));
341   long LEnd = reinterpret_cast<long>(const_cast<char *>(End));
342   cacheflush(LStart, LEnd, BCACHE);
343 #    else
344   cacheflush(const_cast<char *>(Start), Len, BCACHE);
345 #    endif
346 #  endif
347
348 #endif  // end apple
349
350   ValgrindDiscardTranslations(Addr, Len);
351 }
352
353 } // namespace sys
354 } // namespace llvm