1/* 2 * Copyright (c) 2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16#include "ecmascript/platform/map.h" 17 18#include <cerrno> 19#include <sys/mman.h> 20#include <unistd.h> 21 22#include "ecmascript/platform/os.h" 23 24namespace panda::ecmascript { 25MemMap PageMap(size_t size, int prot, size_t alignment, void *addr, int flags) 26{ 27 ASSERT(size == AlignUp(size, PageSize())); 28 ASSERT(alignment == AlignUp(alignment, PageSize())); 29 size_t allocSize = size + alignment; 30 int newFlags = static_cast<int>(MAP_PRIVATE | MAP_ANONYMOUS | static_cast<unsigned int>(flags)); 31 void *result = mmap(addr, allocSize, prot, newFlags, -1, 0); 32 if (reinterpret_cast<intptr_t>(result) == -1) { 33 LOG_ECMA(FATAL) << "mmap failed with error code:" << strerror(errno); 34 } 35 if (alignment != 0) { 36 auto alignResult = AlignUp(reinterpret_cast<uintptr_t>(result), alignment); 37 size_t leftSize = alignResult - reinterpret_cast<uintptr_t>(result); 38 size_t rightSize = alignment - leftSize; 39 void *alignEndResult = reinterpret_cast<void *>(alignResult + size); 40 munmap(result, leftSize); 41 munmap(alignEndResult, rightSize); 42 result = reinterpret_cast<void *>(alignResult); 43 } 44 return MemMap(result, size); 45} 46 47void PageUnmap(MemMap it) 48{ 49 munmap(it.GetMem(), it.GetSize()); 50} 51 52MemMap MachineCodePageMap(size_t size, int prot, size_t alignment) 53{ 54 MemMap memMap = PageMap(size, prot, alignment); 55 PageTag(memMap.GetMem(), memMap.GetSize(), PageTagType::MACHINE_CODE); 56 return memMap; 57} 58 59void MachineCodePageUnmap(MemMap it) 60{ 61 PageClearTag(it.GetMem(), it.GetSize()); 62 if (!PageProtect(it.GetMem(), it.GetSize(), PAGE_PROT_NONE)) { 63 return; 64 } 65 PageUnmap(it); 66} 67 68void PageRelease(void *mem, size_t size) 69{ 70 madvise(mem, size, MADV_DONTNEED); 71} 72 73void PagePreRead(void *mem, size_t size) 74{ 75 madvise(mem, size, MADV_WILLNEED); 76} 77 78void PageTag(void *mem, size_t size, PageTagType type, [[maybe_unused]] const std::string &spaceName, 79 [[maybe_unused]] const uint32_t threadId) 80{ 81#if defined(CROSS_PLATFORM) 82 const char *tag = GetPageTagString(type); 83 PrctlSetVMA(mem, size, tag); 84#else 85 const std::string &tag = GetPageTagString(type, spaceName, threadId); 86 PrctlSetVMA(mem, size, tag.c_str()); 87#endif 88} 89 90void PageClearTag(void *mem, size_t size) 91{ 92 PrctlSetVMA(mem, size, nullptr); 93} 94 95bool PageProtect(void *mem, size_t size, int prot) 96{ 97 int ret = mprotect(mem, size, prot); 98 if (ret != 0) { 99 LOG_ECMA(ERROR) << "PageProtect mem = " << mem << ", size = " << size << 100 ", change to " << prot << " failed, ret = " << ret << ", error code is " << errno; 101 return false; 102 } 103 return true; 104} 105 106size_t PageSize() 107{ 108 return getpagesize(); 109} 110} // namespace panda::ecmascript 111