1f0bfeaa8Sopenharmony_ci/* 2f0bfeaa8Sopenharmony_ci * Copyright (c) 2022 Huawei Device Co., Ltd. 3f0bfeaa8Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4f0bfeaa8Sopenharmony_ci * you may not use this file except in compliance with the License. 5f0bfeaa8Sopenharmony_ci * You may obtain a copy of the License at 6f0bfeaa8Sopenharmony_ci * 7f0bfeaa8Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8f0bfeaa8Sopenharmony_ci * 9f0bfeaa8Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10f0bfeaa8Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11f0bfeaa8Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12f0bfeaa8Sopenharmony_ci * See the License for the specific language governing permissions and 13f0bfeaa8Sopenharmony_ci * limitations under the License. 14f0bfeaa8Sopenharmony_ci */ 15f0bfeaa8Sopenharmony_ci 16f0bfeaa8Sopenharmony_ci#include <sys/mman.h> /* mmap */ 17f0bfeaa8Sopenharmony_ci 18f0bfeaa8Sopenharmony_ci#include "securec.h" 19f0bfeaa8Sopenharmony_ci#include "pm_util.h" 20f0bfeaa8Sopenharmony_ci#include "pm_state_c.h" 21f0bfeaa8Sopenharmony_ci#include "pm_smartptr_util.h" 22f0bfeaa8Sopenharmony_ci#include "pm_log.h" 23f0bfeaa8Sopenharmony_ci 24f0bfeaa8Sopenharmony_ci#include "purgeable_mem.h" 25f0bfeaa8Sopenharmony_ci 26f0bfeaa8Sopenharmony_cinamespace OHOS { 27f0bfeaa8Sopenharmony_cinamespace PurgeableMem { 28f0bfeaa8Sopenharmony_ci#ifdef LOG_TAG 29f0bfeaa8Sopenharmony_ci#undef LOG_TAG 30f0bfeaa8Sopenharmony_ci#endif 31f0bfeaa8Sopenharmony_ci#define LOG_TAG "PurgeableMem" 32f0bfeaa8Sopenharmony_ci 33f0bfeaa8Sopenharmony_cistatic inline size_t RoundUp(size_t val, size_t align) 34f0bfeaa8Sopenharmony_ci{ 35f0bfeaa8Sopenharmony_ci if (val + align < val || val + align < align) { 36f0bfeaa8Sopenharmony_ci PM_HILOG_ERROR(LOG_CORE, "%{public}s: Addition overflow!", __func__); 37f0bfeaa8Sopenharmony_ci return val; 38f0bfeaa8Sopenharmony_ci } 39f0bfeaa8Sopenharmony_ci if (align == 0) { 40f0bfeaa8Sopenharmony_ci return val; 41f0bfeaa8Sopenharmony_ci } 42f0bfeaa8Sopenharmony_ci return ((val + align - 1) / align) * align; 43f0bfeaa8Sopenharmony_ci} 44f0bfeaa8Sopenharmony_ci 45f0bfeaa8Sopenharmony_ciPurgeableMem::PurgeableMem(size_t dataSize, std::unique_ptr<PurgeableMemBuilder> builder) 46f0bfeaa8Sopenharmony_ci{ 47f0bfeaa8Sopenharmony_ci dataPtr_ = nullptr; 48f0bfeaa8Sopenharmony_ci builder_ = nullptr; 49f0bfeaa8Sopenharmony_ci pageTable_ = nullptr; 50f0bfeaa8Sopenharmony_ci buildDataCount_ = 0; 51f0bfeaa8Sopenharmony_ci 52f0bfeaa8Sopenharmony_ci if (dataSize <= 0 || dataSize >= OHOS_MAXIMUM_PURGEABLE_MEMORY) { 53f0bfeaa8Sopenharmony_ci PM_HILOG_DEBUG(LOG_CORE, "Failed to apply for memory"); 54f0bfeaa8Sopenharmony_ci return; 55f0bfeaa8Sopenharmony_ci } 56f0bfeaa8Sopenharmony_ci dataSizeInput_ = dataSize; 57f0bfeaa8Sopenharmony_ci IF_NULL_LOG_ACTION(builder, "%{public}s: input builder nullptr", return); 58f0bfeaa8Sopenharmony_ci 59f0bfeaa8Sopenharmony_ci if (!CreatePurgeableData()) { 60f0bfeaa8Sopenharmony_ci PM_HILOG_DEBUG(LOG_CORE, "Failed to create purgeabledata"); 61f0bfeaa8Sopenharmony_ci return; 62f0bfeaa8Sopenharmony_ci } 63f0bfeaa8Sopenharmony_ci builder_ = std::move(builder); 64f0bfeaa8Sopenharmony_ci PM_HILOG_DEBUG(LOG_CORE, "%{public}s init succ. %{public}s", __func__, ToString().c_str()); 65f0bfeaa8Sopenharmony_ci} 66f0bfeaa8Sopenharmony_ci 67f0bfeaa8Sopenharmony_ciPurgeableMem::~PurgeableMem() 68f0bfeaa8Sopenharmony_ci{ 69f0bfeaa8Sopenharmony_ci PM_HILOG_DEBUG(LOG_CORE, "%{public}s %{public}s", __func__, ToString().c_str()); 70f0bfeaa8Sopenharmony_ci if (dataPtr_) { 71f0bfeaa8Sopenharmony_ci if (munmap(dataPtr_, RoundUp(dataSizeInput_, PAGE_SIZE)) != 0) { 72f0bfeaa8Sopenharmony_ci PM_HILOG_ERROR(LOG_CORE, "%{public}s: munmap dataPtr fail", __func__); 73f0bfeaa8Sopenharmony_ci } else { 74f0bfeaa8Sopenharmony_ci if (UxpteIsEnabled() && !IsPurged()) { 75f0bfeaa8Sopenharmony_ci PM_HILOG_ERROR(LOG_CORE, "%{public}s: munmap dataPtr succ, but uxpte present", __func__); 76f0bfeaa8Sopenharmony_ci } 77f0bfeaa8Sopenharmony_ci dataPtr_ = nullptr; 78f0bfeaa8Sopenharmony_ci } 79f0bfeaa8Sopenharmony_ci } 80f0bfeaa8Sopenharmony_ci builder_.reset(); 81f0bfeaa8Sopenharmony_ci pageTable_.reset(); 82f0bfeaa8Sopenharmony_ci} 83f0bfeaa8Sopenharmony_ci 84f0bfeaa8Sopenharmony_cibool PurgeableMem::IsPurged() 85f0bfeaa8Sopenharmony_ci{ 86f0bfeaa8Sopenharmony_ci IF_NULL_LOG_ACTION(pageTable_, "pageTable_ is nullptrin BeginWrite", return false); 87f0bfeaa8Sopenharmony_ci return !(pageTable_->CheckPresent((uint64_t)dataPtr_, dataSizeInput_)); 88f0bfeaa8Sopenharmony_ci} 89f0bfeaa8Sopenharmony_ci 90f0bfeaa8Sopenharmony_cibool PurgeableMem::CreatePurgeableData() 91f0bfeaa8Sopenharmony_ci{ 92f0bfeaa8Sopenharmony_ci PM_HILOG_DEBUG(LOG_CORE, "%{public}s", __func__); 93f0bfeaa8Sopenharmony_ci pageTable_ = nullptr; 94f0bfeaa8Sopenharmony_ci size_t size = RoundUp(dataSizeInput_, PAGE_SIZE); 95f0bfeaa8Sopenharmony_ci unsigned int utype = MAP_ANONYMOUS; 96f0bfeaa8Sopenharmony_ci utype |= (UxpteIsEnabled() ? MAP_PURGEABLE : MAP_PRIVATE); 97f0bfeaa8Sopenharmony_ci int type = static_cast<int>(utype); 98f0bfeaa8Sopenharmony_ci 99f0bfeaa8Sopenharmony_ci dataPtr_ = mmap(nullptr, size, PROT_READ | PROT_WRITE, type, -1, 0); 100f0bfeaa8Sopenharmony_ci if (dataPtr_ == MAP_FAILED) { 101f0bfeaa8Sopenharmony_ci PM_HILOG_ERROR(LOG_CORE, "%{public}s: mmap fail", __func__); 102f0bfeaa8Sopenharmony_ci dataPtr_ = nullptr; 103f0bfeaa8Sopenharmony_ci return false; 104f0bfeaa8Sopenharmony_ci } 105f0bfeaa8Sopenharmony_ci MAKE_UNIQUE(pageTable_, UxPageTable, "constructor uxpt make_unique fail", return false, (uint64_t)dataPtr_, size); 106f0bfeaa8Sopenharmony_ci return true; 107f0bfeaa8Sopenharmony_ci} 108f0bfeaa8Sopenharmony_ci 109f0bfeaa8Sopenharmony_cibool PurgeableMem::Pin() 110f0bfeaa8Sopenharmony_ci{ 111f0bfeaa8Sopenharmony_ci IF_NULL_LOG_ACTION(pageTable_, "pageTable_ is nullptrin BeginWrite", return false); 112f0bfeaa8Sopenharmony_ci pageTable_->GetUxpte((uint64_t)dataPtr_, dataSizeInput_); 113f0bfeaa8Sopenharmony_ci return true; 114f0bfeaa8Sopenharmony_ci} 115f0bfeaa8Sopenharmony_ci 116f0bfeaa8Sopenharmony_cibool PurgeableMem::Unpin() 117f0bfeaa8Sopenharmony_ci{ 118f0bfeaa8Sopenharmony_ci IF_NULL_LOG_ACTION(pageTable_, "pageTable_ is nullptrin BeginWrite", return false); 119f0bfeaa8Sopenharmony_ci pageTable_->PutUxpte((uint64_t)dataPtr_, dataSizeInput_); 120f0bfeaa8Sopenharmony_ci return true; 121f0bfeaa8Sopenharmony_ci} 122f0bfeaa8Sopenharmony_ci 123f0bfeaa8Sopenharmony_civoid PurgeableMem::AfterRebuildSucc() 124f0bfeaa8Sopenharmony_ci{ 125f0bfeaa8Sopenharmony_ci} 126f0bfeaa8Sopenharmony_ci 127f0bfeaa8Sopenharmony_ciint PurgeableMem::GetPinStatus() const 128f0bfeaa8Sopenharmony_ci{ 129f0bfeaa8Sopenharmony_ci return 0; 130f0bfeaa8Sopenharmony_ci} 131f0bfeaa8Sopenharmony_ci 132f0bfeaa8Sopenharmony_civoid PurgeableMem::ResizeData(size_t newSize) 133f0bfeaa8Sopenharmony_ci{ 134f0bfeaa8Sopenharmony_ci if (newSize <= 0 || newSize >= OHOS_MAXIMUM_PURGEABLE_MEMORY) { 135f0bfeaa8Sopenharmony_ci PM_HILOG_DEBUG(LOG_CORE, "Failed to apply for memory"); 136f0bfeaa8Sopenharmony_ci return; 137f0bfeaa8Sopenharmony_ci } 138f0bfeaa8Sopenharmony_ci if (dataPtr_) { 139f0bfeaa8Sopenharmony_ci if (munmap(dataPtr_, RoundUp(dataSizeInput_, PAGE_SIZE)) != 0) { 140f0bfeaa8Sopenharmony_ci PM_HILOG_ERROR(LOG_CORE, "%{public}s: munmap dataPtr fail", __func__); 141f0bfeaa8Sopenharmony_ci } else { 142f0bfeaa8Sopenharmony_ci dataPtr_ = nullptr; 143f0bfeaa8Sopenharmony_ci } 144f0bfeaa8Sopenharmony_ci } 145f0bfeaa8Sopenharmony_ci dataSizeInput_ = newSize; 146f0bfeaa8Sopenharmony_ci if (!CreatePurgeableData()) { 147f0bfeaa8Sopenharmony_ci PM_HILOG_DEBUG(LOG_CORE, "Failed to create purgeabledata"); 148f0bfeaa8Sopenharmony_ci return; 149f0bfeaa8Sopenharmony_ci } 150f0bfeaa8Sopenharmony_ci} 151f0bfeaa8Sopenharmony_ci 152f0bfeaa8Sopenharmony_ciinline std::string PurgeableMem::ToString() const 153f0bfeaa8Sopenharmony_ci{ 154f0bfeaa8Sopenharmony_ci std::string dataptrStr = dataPtr_ ? std::to_string((unsigned long long)dataPtr_) : "0"; 155f0bfeaa8Sopenharmony_ci std::string pageTableStr = pageTable_ ? pageTable_->ToString() : "0"; 156f0bfeaa8Sopenharmony_ci return "dataAddr:" + dataptrStr + " dataSizeInput:" + std::to_string(dataSizeInput_) + 157f0bfeaa8Sopenharmony_ci " " + pageTableStr; 158f0bfeaa8Sopenharmony_ci} 159f0bfeaa8Sopenharmony_ci} /* namespace PurgeableMem */ 160f0bfeaa8Sopenharmony_ci} /* namespace OHOS */ 161