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 <stdlib.h> /* malloc */ 17f0bfeaa8Sopenharmony_ci#include <sys/mman.h> /* mmap */ 18f0bfeaa8Sopenharmony_ci#include <pthread.h> 19f0bfeaa8Sopenharmony_ci#include <stdio.h> /* FILE */ 20f0bfeaa8Sopenharmony_ci 21f0bfeaa8Sopenharmony_ci#include "securec.h" 22f0bfeaa8Sopenharmony_ci#include "pm_ptr_util.h" 23f0bfeaa8Sopenharmony_ci#include "pm_util.h" 24f0bfeaa8Sopenharmony_ci#include "pm_state_c.h" 25f0bfeaa8Sopenharmony_ci#include "ux_page_table_c.h" 26f0bfeaa8Sopenharmony_ci#include "purgeable_mem_builder_c.h" 27f0bfeaa8Sopenharmony_ci#include "pm_log_c.h" 28f0bfeaa8Sopenharmony_ci#include "purgeable_mem_c.h" 29f0bfeaa8Sopenharmony_ci 30f0bfeaa8Sopenharmony_ci#undef LOG_TAG 31f0bfeaa8Sopenharmony_ci#define LOG_TAG "PurgeableMemC" 32f0bfeaa8Sopenharmony_ci 33f0bfeaa8Sopenharmony_cistruct PurgMem { 34f0bfeaa8Sopenharmony_ci void *dataPtr; 35f0bfeaa8Sopenharmony_ci size_t dataSizeInput; 36f0bfeaa8Sopenharmony_ci struct PurgMemBuilder *builder; 37f0bfeaa8Sopenharmony_ci UxPageTableStruct *uxPageTable; 38f0bfeaa8Sopenharmony_ci pthread_rwlock_t rwlock; 39f0bfeaa8Sopenharmony_ci unsigned int buildDataCount; 40f0bfeaa8Sopenharmony_ci}; 41f0bfeaa8Sopenharmony_ci 42f0bfeaa8Sopenharmony_cistatic inline void LogPurgMemInfo(struct PurgMem *obj) 43f0bfeaa8Sopenharmony_ci{ 44f0bfeaa8Sopenharmony_ci if (obj == NULL) { 45f0bfeaa8Sopenharmony_ci PM_HILOG_ERROR_C(LOG_CORE, "%{public}s: obj is NULL!", __func__); 46f0bfeaa8Sopenharmony_ci return; 47f0bfeaa8Sopenharmony_ci } 48f0bfeaa8Sopenharmony_ci PM_HILOG_INFO_C(LOG_CORE, "purgMemObj(%{public}lx) dataPtr(%{public}lx) dataSizeInput(%{public}zu)" 49f0bfeaa8Sopenharmony_ci " builderPtr(%{public}lx) uxpt(%{public}lx)", 50f0bfeaa8Sopenharmony_ci (unsigned long)obj, (unsigned long)(obj->dataPtr), obj->dataSizeInput, 51f0bfeaa8Sopenharmony_ci (unsigned long)(obj->builder), (unsigned long)(obj->uxPageTable)); 52f0bfeaa8Sopenharmony_ci} 53f0bfeaa8Sopenharmony_ci 54f0bfeaa8Sopenharmony_cistatic inline size_t RoundUp(size_t val, size_t align) 55f0bfeaa8Sopenharmony_ci{ 56f0bfeaa8Sopenharmony_ci if (val + align < val || val + align < align) { 57f0bfeaa8Sopenharmony_ci PM_HILOG_ERROR_C(LOG_CORE, "%{public}s: Addition overflow!", __func__); 58f0bfeaa8Sopenharmony_ci return val; 59f0bfeaa8Sopenharmony_ci } 60f0bfeaa8Sopenharmony_ci if (align == 0) { 61f0bfeaa8Sopenharmony_ci return val; 62f0bfeaa8Sopenharmony_ci } 63f0bfeaa8Sopenharmony_ci return ((val + align - 1) / align) * align; 64f0bfeaa8Sopenharmony_ci} 65f0bfeaa8Sopenharmony_ci 66f0bfeaa8Sopenharmony_cistatic bool IsPurgMemPtrValid(struct PurgMem *purgObj); 67f0bfeaa8Sopenharmony_cistatic bool IsPurged(struct PurgMem *purgObj); 68f0bfeaa8Sopenharmony_cistatic int TypeCast(void); 69f0bfeaa8Sopenharmony_ci 70f0bfeaa8Sopenharmony_cistatic struct PurgMem *PurgMemCreate_(size_t len, struct PurgMemBuilder *builder) 71f0bfeaa8Sopenharmony_ci{ 72f0bfeaa8Sopenharmony_ci /* PurgMemObj allow no builder temporaily */ 73f0bfeaa8Sopenharmony_ci struct PurgMem *pugObj = NULL; 74f0bfeaa8Sopenharmony_ci pugObj = (struct PurgMem *)malloc(sizeof(struct PurgMem)); 75f0bfeaa8Sopenharmony_ci if (!pugObj) { 76f0bfeaa8Sopenharmony_ci PM_HILOG_ERROR_C(LOG_CORE, "%{public}s: malloc struct PurgMem fail", __func__); 77f0bfeaa8Sopenharmony_ci return NULL; 78f0bfeaa8Sopenharmony_ci } 79f0bfeaa8Sopenharmony_ci size_t size = RoundUp(len, PAGE_SIZE); 80f0bfeaa8Sopenharmony_ci int type = TypeCast(); 81f0bfeaa8Sopenharmony_ci pugObj->dataPtr = mmap(NULL, size, PROT_READ | PROT_WRITE, type, -1, 0); 82f0bfeaa8Sopenharmony_ci if (pugObj->dataPtr == MAP_FAILED) { 83f0bfeaa8Sopenharmony_ci PM_HILOG_ERROR_C(LOG_CORE, "%{public}s: mmap dataPtr fail", __func__); 84f0bfeaa8Sopenharmony_ci pugObj->dataPtr = NULL; 85f0bfeaa8Sopenharmony_ci goto free_pug_obj; 86f0bfeaa8Sopenharmony_ci } 87f0bfeaa8Sopenharmony_ci 88f0bfeaa8Sopenharmony_ci pugObj->uxPageTable = (UxPageTableStruct *)malloc(UxPageTableSize()); 89f0bfeaa8Sopenharmony_ci if (!(pugObj->uxPageTable)) { 90f0bfeaa8Sopenharmony_ci PM_HILOG_ERROR_C(LOG_CORE, "%{public}s: malloc UxPageTableStruct fail", __func__); 91f0bfeaa8Sopenharmony_ci goto unmap_data; 92f0bfeaa8Sopenharmony_ci } 93f0bfeaa8Sopenharmony_ci PMState err = InitUxPageTable(pugObj->uxPageTable, (uint64_t)(pugObj->dataPtr), size); /* dataPtr is aligned */ 94f0bfeaa8Sopenharmony_ci if (err != PM_OK) { 95f0bfeaa8Sopenharmony_ci PM_HILOG_ERROR_C(LOG_CORE, 96f0bfeaa8Sopenharmony_ci "%{public}s: InitUxPageTable fail, %{public}s", __func__, GetPMStateName(err)); 97f0bfeaa8Sopenharmony_ci goto free_uxpt; 98f0bfeaa8Sopenharmony_ci } 99f0bfeaa8Sopenharmony_ci int lockInitRet = pthread_rwlock_init(&(pugObj->rwlock), NULL); 100f0bfeaa8Sopenharmony_ci if (lockInitRet != 0) { 101f0bfeaa8Sopenharmony_ci PM_HILOG_ERROR_C(LOG_CORE, "%{public}s: pthread_rwlock_init fail, %{public}d", __func__, lockInitRet); 102f0bfeaa8Sopenharmony_ci goto deinit_upt; 103f0bfeaa8Sopenharmony_ci } 104f0bfeaa8Sopenharmony_ci pugObj->builder = builder; 105f0bfeaa8Sopenharmony_ci pugObj->dataSizeInput = len; 106f0bfeaa8Sopenharmony_ci pugObj->buildDataCount = 0; 107f0bfeaa8Sopenharmony_ci 108f0bfeaa8Sopenharmony_ci PM_HILOG_INFO_C(LOG_CORE, "%{public}s: LogPurgMemInfo:", __func__); 109f0bfeaa8Sopenharmony_ci LogPurgMemInfo(pugObj); 110f0bfeaa8Sopenharmony_ci return pugObj; 111f0bfeaa8Sopenharmony_ci 112f0bfeaa8Sopenharmony_cideinit_upt: 113f0bfeaa8Sopenharmony_ci DeinitUxPageTable(pugObj->uxPageTable); 114f0bfeaa8Sopenharmony_cifree_uxpt: 115f0bfeaa8Sopenharmony_ci free(pugObj->uxPageTable); 116f0bfeaa8Sopenharmony_ci pugObj->uxPageTable = NULL; 117f0bfeaa8Sopenharmony_ciunmap_data: 118f0bfeaa8Sopenharmony_ci munmap(pugObj->dataPtr, size); 119f0bfeaa8Sopenharmony_ci pugObj->dataPtr = NULL; 120f0bfeaa8Sopenharmony_cifree_pug_obj: 121f0bfeaa8Sopenharmony_ci free(pugObj); 122f0bfeaa8Sopenharmony_ci pugObj = NULL; 123f0bfeaa8Sopenharmony_ci 124f0bfeaa8Sopenharmony_ci return NULL; 125f0bfeaa8Sopenharmony_ci} 126f0bfeaa8Sopenharmony_ci 127f0bfeaa8Sopenharmony_cistruct PurgMem *PurgMemCreate(size_t len, PurgMemModifyFunc func, void *funcPara) 128f0bfeaa8Sopenharmony_ci{ 129f0bfeaa8Sopenharmony_ci if (len == 0) { 130f0bfeaa8Sopenharmony_ci PM_HILOG_ERROR_C(LOG_CORE, "%{public}s: input len 0", __func__); 131f0bfeaa8Sopenharmony_ci return NULL; 132f0bfeaa8Sopenharmony_ci } 133f0bfeaa8Sopenharmony_ci /* a PurgMemObj must have builder */ 134f0bfeaa8Sopenharmony_ci IF_NULL_LOG_ACTION(func, "%{public}s: input func is NULL", return NULL); 135f0bfeaa8Sopenharmony_ci struct PurgMem *purgMemObj = PurgMemCreate_(len, NULL); 136f0bfeaa8Sopenharmony_ci /* create fail */ 137f0bfeaa8Sopenharmony_ci if (!purgMemObj) { 138f0bfeaa8Sopenharmony_ci return purgMemObj; 139f0bfeaa8Sopenharmony_ci } 140f0bfeaa8Sopenharmony_ci 141f0bfeaa8Sopenharmony_ci if (PurgMemAppendModify(purgMemObj, func, funcPara)) { 142f0bfeaa8Sopenharmony_ci return purgMemObj; 143f0bfeaa8Sopenharmony_ci } 144f0bfeaa8Sopenharmony_ci 145f0bfeaa8Sopenharmony_ci /* append func fail meas create builder failed */ 146f0bfeaa8Sopenharmony_ci PM_HILOG_ERROR_C(LOG_CORE, "%{public}s: append mod func fail", __func__); 147f0bfeaa8Sopenharmony_ci if (!PurgMemDestroy(purgMemObj)) { 148f0bfeaa8Sopenharmony_ci PM_HILOG_ERROR_C(LOG_CORE, "%{public}s: destroy PurgMem fail after append modFunc fail", __func__); 149f0bfeaa8Sopenharmony_ci } 150f0bfeaa8Sopenharmony_ci return NULL; 151f0bfeaa8Sopenharmony_ci} 152f0bfeaa8Sopenharmony_ci 153f0bfeaa8Sopenharmony_cibool PurgMemDestroy(struct PurgMem *purgObj) 154f0bfeaa8Sopenharmony_ci{ 155f0bfeaa8Sopenharmony_ci IF_NULL_LOG_ACTION(purgObj, "input is NULL", return true); 156f0bfeaa8Sopenharmony_ci PM_HILOG_INFO_C(LOG_CORE, "%{public}s: LogPurgMemInfo:", __func__); 157f0bfeaa8Sopenharmony_ci LogPurgMemInfo(purgObj); 158f0bfeaa8Sopenharmony_ci 159f0bfeaa8Sopenharmony_ci PMState err = PM_OK; 160f0bfeaa8Sopenharmony_ci /* destroy rwlock */ 161f0bfeaa8Sopenharmony_ci int ret = pthread_rwlock_destroy(&(purgObj->rwlock)); 162f0bfeaa8Sopenharmony_ci if (ret != 0) { 163f0bfeaa8Sopenharmony_ci PM_HILOG_ERROR_C(LOG_CORE, "%{public}s: pthread_rwlock_destroy fail, %{public}d", __func__, ret); 164f0bfeaa8Sopenharmony_ci } 165f0bfeaa8Sopenharmony_ci /* destroy builder */ 166f0bfeaa8Sopenharmony_ci if (purgObj->builder) { 167f0bfeaa8Sopenharmony_ci if (!PurgMemBuilderDestroy(purgObj->builder)) { 168f0bfeaa8Sopenharmony_ci PM_HILOG_ERROR_C(LOG_CORE, "%{public}s: PurgMemBuilderDestroy fail", __func__); 169f0bfeaa8Sopenharmony_ci err = PMB_DESTORY_FAIL; 170f0bfeaa8Sopenharmony_ci } else { 171f0bfeaa8Sopenharmony_ci purgObj->builder = NULL; 172f0bfeaa8Sopenharmony_ci } 173f0bfeaa8Sopenharmony_ci } 174f0bfeaa8Sopenharmony_ci /* unmap purgeable mem region */ 175f0bfeaa8Sopenharmony_ci if (purgObj->dataPtr) { 176f0bfeaa8Sopenharmony_ci size_t size = RoundUp(purgObj->dataSizeInput, PAGE_SIZE); 177f0bfeaa8Sopenharmony_ci if (munmap(purgObj->dataPtr, size) != 0) { 178f0bfeaa8Sopenharmony_ci PM_HILOG_ERROR_C(LOG_CORE, "%{public}s: munmap dataPtr fail", __func__); 179f0bfeaa8Sopenharmony_ci err = PM_UNMAP_PURG_FAIL; 180f0bfeaa8Sopenharmony_ci } else { 181f0bfeaa8Sopenharmony_ci /* double check munmap result: if uxpte is set to no_present */ 182f0bfeaa8Sopenharmony_ci if (UxpteIsEnabled() && !IsPurged(purgObj)) { 183f0bfeaa8Sopenharmony_ci PM_HILOG_ERROR_C(LOG_CORE, "%{public}s: munmap dataPtr succ, but uxpte present", __func__); 184f0bfeaa8Sopenharmony_ci err = PM_UXPT_PRESENT_DATA_PURGED; 185f0bfeaa8Sopenharmony_ci } 186f0bfeaa8Sopenharmony_ci purgObj->dataPtr = NULL; 187f0bfeaa8Sopenharmony_ci } 188f0bfeaa8Sopenharmony_ci } 189f0bfeaa8Sopenharmony_ci /* unmap uxpt */ 190f0bfeaa8Sopenharmony_ci if (purgObj->uxPageTable) { 191f0bfeaa8Sopenharmony_ci PMState deinitRet = DeinitUxPageTable(purgObj->uxPageTable); 192f0bfeaa8Sopenharmony_ci if (deinitRet != PM_OK) { 193f0bfeaa8Sopenharmony_ci PM_HILOG_ERROR_C(LOG_CORE, 194f0bfeaa8Sopenharmony_ci "%{public}s: deinit upt fail, %{public}s", __func__, GetPMStateName(deinitRet)); 195f0bfeaa8Sopenharmony_ci err = deinitRet; 196f0bfeaa8Sopenharmony_ci } else { 197f0bfeaa8Sopenharmony_ci free(purgObj->uxPageTable); 198f0bfeaa8Sopenharmony_ci purgObj->uxPageTable = NULL; 199f0bfeaa8Sopenharmony_ci } 200f0bfeaa8Sopenharmony_ci } 201f0bfeaa8Sopenharmony_ci 202f0bfeaa8Sopenharmony_ci if (err == PM_OK) { 203f0bfeaa8Sopenharmony_ci free(purgObj); 204f0bfeaa8Sopenharmony_ci purgObj = NULL; /* set input para NULL to avoid UAF */ 205f0bfeaa8Sopenharmony_ci PM_HILOG_ERROR_C(LOG_CORE, "%{public}s: succ", __func__); 206f0bfeaa8Sopenharmony_ci return true; 207f0bfeaa8Sopenharmony_ci } 208f0bfeaa8Sopenharmony_ci PM_HILOG_ERROR_C(LOG_CORE, "%{public}s: fail, %{public}s", __func__, GetPMStateName(err)); 209f0bfeaa8Sopenharmony_ci return false; 210f0bfeaa8Sopenharmony_ci} 211f0bfeaa8Sopenharmony_ci 212f0bfeaa8Sopenharmony_cistatic bool IsPurgMemPtrValid(struct PurgMem *purgObj) 213f0bfeaa8Sopenharmony_ci{ 214f0bfeaa8Sopenharmony_ci IF_NULL_LOG_ACTION(purgObj, "obj is NULL", return false); 215f0bfeaa8Sopenharmony_ci IF_NULL_LOG_ACTION(purgObj->dataPtr, "dataPtr is NULL", return false); 216f0bfeaa8Sopenharmony_ci IF_NULL_LOG_ACTION(purgObj->uxPageTable, "pageTable is NULL", return false); 217f0bfeaa8Sopenharmony_ci IF_NULL_LOG_ACTION(purgObj->builder, "builder is NULL", return false); 218f0bfeaa8Sopenharmony_ci 219f0bfeaa8Sopenharmony_ci return true; 220f0bfeaa8Sopenharmony_ci} 221f0bfeaa8Sopenharmony_ci 222f0bfeaa8Sopenharmony_cistatic inline bool PurgMemBuildData(struct PurgMem *purgObj) 223f0bfeaa8Sopenharmony_ci{ 224f0bfeaa8Sopenharmony_ci bool succ = false; 225f0bfeaa8Sopenharmony_ci /* clear content before rebuild */ 226f0bfeaa8Sopenharmony_ci if (memset_s(purgObj->dataPtr, RoundUp(purgObj->dataSizeInput, PAGE_SIZE), 0, purgObj->dataSizeInput) != EOK) { 227f0bfeaa8Sopenharmony_ci PM_HILOG_ERROR_C(LOG_CORE, "%{public}s, clear content fail", __func__); 228f0bfeaa8Sopenharmony_ci return succ; 229f0bfeaa8Sopenharmony_ci } 230f0bfeaa8Sopenharmony_ci /* @purgObj->builder is not NULL since it is checked by IsPurgMemPtrValid() before */ 231f0bfeaa8Sopenharmony_ci succ = PurgMemBuilderBuildAll(purgObj->builder, purgObj->dataPtr, purgObj->dataSizeInput); 232f0bfeaa8Sopenharmony_ci if (succ) { 233f0bfeaa8Sopenharmony_ci purgObj->buildDataCount++; 234f0bfeaa8Sopenharmony_ci } 235f0bfeaa8Sopenharmony_ci return succ; 236f0bfeaa8Sopenharmony_ci} 237f0bfeaa8Sopenharmony_ci 238f0bfeaa8Sopenharmony_cistatic PMState TryBeginRead(struct PurgMem *purgObj) 239f0bfeaa8Sopenharmony_ci{ 240f0bfeaa8Sopenharmony_ci int rwlockRet = pthread_rwlock_rdlock(&(purgObj->rwlock)); 241f0bfeaa8Sopenharmony_ci if (rwlockRet != 0) { 242f0bfeaa8Sopenharmony_ci PM_HILOG_ERROR_C(LOG_CORE, "%{public}s: rdlock fail. %{public}d", __func__, rwlockRet); 243f0bfeaa8Sopenharmony_ci return PM_LOCK_READ_FAIL; 244f0bfeaa8Sopenharmony_ci } 245f0bfeaa8Sopenharmony_ci 246f0bfeaa8Sopenharmony_ci if (!IsPurged(purgObj)) { 247f0bfeaa8Sopenharmony_ci PM_HILOG_INFO_C(LOG_CORE, 248f0bfeaa8Sopenharmony_ci "%{public}s: not purged, return true. MAP_PUG=0x%{public}x", __func__, MAP_PURGEABLE); 249f0bfeaa8Sopenharmony_ci return PM_DATA_NO_PURGED; 250f0bfeaa8Sopenharmony_ci } 251f0bfeaa8Sopenharmony_ci 252f0bfeaa8Sopenharmony_ci rwlockRet = pthread_rwlock_unlock(&(purgObj->rwlock)); 253f0bfeaa8Sopenharmony_ci if (rwlockRet != 0) { 254f0bfeaa8Sopenharmony_ci PM_HILOG_ERROR_C(LOG_CORE, "%{public}s: rd unlock fail. %{public}d", __func__, rwlockRet); 255f0bfeaa8Sopenharmony_ci return PM_UNLOCK_READ_FAIL; 256f0bfeaa8Sopenharmony_ci } 257f0bfeaa8Sopenharmony_ci 258f0bfeaa8Sopenharmony_ci return PM_DATA_PURGED; 259f0bfeaa8Sopenharmony_ci} 260f0bfeaa8Sopenharmony_ci 261f0bfeaa8Sopenharmony_cistatic PMState BeginReadBuildData(struct PurgMem *purgObj) 262f0bfeaa8Sopenharmony_ci{ 263f0bfeaa8Sopenharmony_ci bool rebuildRet = false; 264f0bfeaa8Sopenharmony_ci int rwlockRet = pthread_rwlock_wrlock(&(purgObj->rwlock)); 265f0bfeaa8Sopenharmony_ci if (rwlockRet) { 266f0bfeaa8Sopenharmony_ci PM_HILOG_ERROR_C(LOG_CORE, "%{public}s: wrlock fail. %{public}d", __func__, rwlockRet); 267f0bfeaa8Sopenharmony_ci return PM_LOCK_WRITE_FAIL; 268f0bfeaa8Sopenharmony_ci } 269f0bfeaa8Sopenharmony_ci 270f0bfeaa8Sopenharmony_ci if (IsPurged(purgObj)) { 271f0bfeaa8Sopenharmony_ci rebuildRet = PurgMemBuildData(purgObj); 272f0bfeaa8Sopenharmony_ci PM_HILOG_ERROR_C(LOG_CORE, 273f0bfeaa8Sopenharmony_ci "%{public}s: purged, after built %{public}s", __func__, rebuildRet ? "succ" : "fail"); 274f0bfeaa8Sopenharmony_ci } 275f0bfeaa8Sopenharmony_ci 276f0bfeaa8Sopenharmony_ci rwlockRet = pthread_rwlock_unlock(&(purgObj->rwlock)); 277f0bfeaa8Sopenharmony_ci if (rwlockRet != 0) { 278f0bfeaa8Sopenharmony_ci PM_HILOG_ERROR_C(LOG_CORE, "%{public}s: wr unlock fail. %{public}d", __func__, rwlockRet); 279f0bfeaa8Sopenharmony_ci return PM_UNLOCK_WRITE_FAIL; 280f0bfeaa8Sopenharmony_ci } 281f0bfeaa8Sopenharmony_ci 282f0bfeaa8Sopenharmony_ci if (!rebuildRet) { 283f0bfeaa8Sopenharmony_ci return PMB_BUILD_ALL_FAIL; 284f0bfeaa8Sopenharmony_ci } 285f0bfeaa8Sopenharmony_ci 286f0bfeaa8Sopenharmony_ci return PMB_BUILD_ALL_SUCC; 287f0bfeaa8Sopenharmony_ci} 288f0bfeaa8Sopenharmony_ci 289f0bfeaa8Sopenharmony_cibool PurgMemBeginRead(struct PurgMem *purgObj) 290f0bfeaa8Sopenharmony_ci{ 291f0bfeaa8Sopenharmony_ci if (!IsPurgMemPtrValid(purgObj)) { 292f0bfeaa8Sopenharmony_ci PM_HILOG_ERROR_C(LOG_CORE, "%{public}s: para is invalid", __func__); 293f0bfeaa8Sopenharmony_ci return false; 294f0bfeaa8Sopenharmony_ci } 295f0bfeaa8Sopenharmony_ci PM_HILOG_INFO_C(LOG_CORE, "%{public}s: LogPurgMemInfo:", __func__); 296f0bfeaa8Sopenharmony_ci LogPurgMemInfo(purgObj); 297f0bfeaa8Sopenharmony_ci bool ret = false; 298f0bfeaa8Sopenharmony_ci PMState err = PM_OK; 299f0bfeaa8Sopenharmony_ci UxpteGet(purgObj->uxPageTable, (uint64_t)(purgObj->dataPtr), purgObj->dataSizeInput); 300f0bfeaa8Sopenharmony_ci while (true) { 301f0bfeaa8Sopenharmony_ci err = TryBeginRead(purgObj); 302f0bfeaa8Sopenharmony_ci if (err == PM_DATA_NO_PURGED) { 303f0bfeaa8Sopenharmony_ci ret = true; 304f0bfeaa8Sopenharmony_ci break; 305f0bfeaa8Sopenharmony_ci } else if (err != PM_DATA_PURGED) { 306f0bfeaa8Sopenharmony_ci break; 307f0bfeaa8Sopenharmony_ci } 308f0bfeaa8Sopenharmony_ci 309f0bfeaa8Sopenharmony_ci err = BeginReadBuildData(purgObj); 310f0bfeaa8Sopenharmony_ci if (err != PMB_BUILD_ALL_SUCC) { 311f0bfeaa8Sopenharmony_ci ret = false; 312f0bfeaa8Sopenharmony_ci break; 313f0bfeaa8Sopenharmony_ci } 314f0bfeaa8Sopenharmony_ci } 315f0bfeaa8Sopenharmony_ci 316f0bfeaa8Sopenharmony_ci if (!ret) { 317f0bfeaa8Sopenharmony_ci PM_HILOG_ERROR_C(LOG_CORE, "%{public}s: %{public}s, UxptePut.", __func__, GetPMStateName(err)); 318f0bfeaa8Sopenharmony_ci UxptePut(purgObj->uxPageTable, (uint64_t)(purgObj->dataPtr), purgObj->dataSizeInput); 319f0bfeaa8Sopenharmony_ci } 320f0bfeaa8Sopenharmony_ci return ret; 321f0bfeaa8Sopenharmony_ci} 322f0bfeaa8Sopenharmony_ci 323f0bfeaa8Sopenharmony_cibool PurgMemBeginWrite(struct PurgMem *purgObj) 324f0bfeaa8Sopenharmony_ci{ 325f0bfeaa8Sopenharmony_ci if (!IsPurgMemPtrValid(purgObj)) { 326f0bfeaa8Sopenharmony_ci PM_HILOG_ERROR_C(LOG_CORE, "%{public}s: para is invalid", __func__); 327f0bfeaa8Sopenharmony_ci return false; 328f0bfeaa8Sopenharmony_ci } 329f0bfeaa8Sopenharmony_ci PM_HILOG_INFO_C(LOG_CORE, "%{public}s: LogPurgMemInfo:", __func__); 330f0bfeaa8Sopenharmony_ci LogPurgMemInfo(purgObj); 331f0bfeaa8Sopenharmony_ci int rwlockRet = 0; 332f0bfeaa8Sopenharmony_ci bool rebuildRet = false; 333f0bfeaa8Sopenharmony_ci PMState err = PM_OK; 334f0bfeaa8Sopenharmony_ci 335f0bfeaa8Sopenharmony_ci UxpteGet(purgObj->uxPageTable, (uint64_t)(purgObj->dataPtr), purgObj->dataSizeInput); 336f0bfeaa8Sopenharmony_ci 337f0bfeaa8Sopenharmony_ci rwlockRet = pthread_rwlock_wrlock(&(purgObj->rwlock)); 338f0bfeaa8Sopenharmony_ci if (rwlockRet != 0) { 339f0bfeaa8Sopenharmony_ci PM_HILOG_ERROR_C(LOG_CORE, "%{public}s: wrlock fail. %{public}d", __func__, rwlockRet); 340f0bfeaa8Sopenharmony_ci err = PM_LOCK_WRITE_FAIL; 341f0bfeaa8Sopenharmony_ci PM_HILOG_ERROR_C(LOG_CORE, "%{public}s: %{public}s, return false, UxptePut.", __func__, GetPMStateName(err)); 342f0bfeaa8Sopenharmony_ci UxptePut(purgObj->uxPageTable, (uint64_t)(purgObj->dataPtr), purgObj->dataSizeInput); 343f0bfeaa8Sopenharmony_ci return false; 344f0bfeaa8Sopenharmony_ci } 345f0bfeaa8Sopenharmony_ci 346f0bfeaa8Sopenharmony_ci if (!IsPurged(purgObj)) { 347f0bfeaa8Sopenharmony_ci return true; 348f0bfeaa8Sopenharmony_ci } 349f0bfeaa8Sopenharmony_ci 350f0bfeaa8Sopenharmony_ci /* data is purged */ 351f0bfeaa8Sopenharmony_ci rebuildRet = PurgMemBuildData(purgObj); 352f0bfeaa8Sopenharmony_ci PM_HILOG_INFO_C(LOG_CORE, "%{public}s: purged, built %{public}s", __func__, rebuildRet ? "succ" : "fail"); 353f0bfeaa8Sopenharmony_ci if (rebuildRet) { 354f0bfeaa8Sopenharmony_ci return true; 355f0bfeaa8Sopenharmony_ci } 356f0bfeaa8Sopenharmony_ci /* data is purged and rebuild failed. return false */ 357f0bfeaa8Sopenharmony_ci err = PMB_BUILD_ALL_FAIL; 358f0bfeaa8Sopenharmony_ci rwlockRet = pthread_rwlock_unlock(&(purgObj->rwlock)); 359f0bfeaa8Sopenharmony_ci if (rwlockRet != 0) { 360f0bfeaa8Sopenharmony_ci PM_HILOG_ERROR_C(LOG_CORE, "%{public}s: wr unlock fail. %{public}d", __func__, rwlockRet); 361f0bfeaa8Sopenharmony_ci } 362f0bfeaa8Sopenharmony_ci 363f0bfeaa8Sopenharmony_ci PM_HILOG_ERROR_C(LOG_CORE, "%{public}s: %{public}s, return false, UxptePut.", __func__, GetPMStateName(err)); 364f0bfeaa8Sopenharmony_ci UxptePut(purgObj->uxPageTable, (uint64_t)(purgObj->dataPtr), purgObj->dataSizeInput); 365f0bfeaa8Sopenharmony_ci return false; 366f0bfeaa8Sopenharmony_ci} 367f0bfeaa8Sopenharmony_ci 368f0bfeaa8Sopenharmony_cistatic inline void EndAccessPurgMem(struct PurgMem *purgObj) 369f0bfeaa8Sopenharmony_ci{ 370f0bfeaa8Sopenharmony_ci if (!IsPurgMemPtrValid(purgObj)) { 371f0bfeaa8Sopenharmony_ci PM_HILOG_ERROR_C(LOG_CORE, "%{public}s: para is invalid", __func__); 372f0bfeaa8Sopenharmony_ci return; 373f0bfeaa8Sopenharmony_ci } 374f0bfeaa8Sopenharmony_ci int rwlockRet = 0; 375f0bfeaa8Sopenharmony_ci rwlockRet = pthread_rwlock_unlock(&(purgObj->rwlock)); 376f0bfeaa8Sopenharmony_ci if (rwlockRet != 0) { 377f0bfeaa8Sopenharmony_ci PM_HILOG_ERROR_C(LOG_CORE, "%{public}s: unlock fail. %{public}d", __func__, rwlockRet); 378f0bfeaa8Sopenharmony_ci } 379f0bfeaa8Sopenharmony_ci UxptePut(purgObj->uxPageTable, (uint64_t)(purgObj->dataPtr), purgObj->dataSizeInput); 380f0bfeaa8Sopenharmony_ci} 381f0bfeaa8Sopenharmony_ci 382f0bfeaa8Sopenharmony_civoid PurgMemEndRead(struct PurgMem *purgObj) 383f0bfeaa8Sopenharmony_ci{ 384f0bfeaa8Sopenharmony_ci EndAccessPurgMem(purgObj); 385f0bfeaa8Sopenharmony_ci} 386f0bfeaa8Sopenharmony_ci 387f0bfeaa8Sopenharmony_civoid PurgMemEndWrite(struct PurgMem *purgObj) 388f0bfeaa8Sopenharmony_ci{ 389f0bfeaa8Sopenharmony_ci EndAccessPurgMem(purgObj); 390f0bfeaa8Sopenharmony_ci} 391f0bfeaa8Sopenharmony_ci 392f0bfeaa8Sopenharmony_civoid *PurgMemGetContent(struct PurgMem *purgObj) 393f0bfeaa8Sopenharmony_ci{ 394f0bfeaa8Sopenharmony_ci if (!IsPurgMemPtrValid(purgObj)) { 395f0bfeaa8Sopenharmony_ci PM_HILOG_ERROR_C(LOG_CORE, "%{public}s: para is invalid", __func__); 396f0bfeaa8Sopenharmony_ci return NULL; 397f0bfeaa8Sopenharmony_ci } 398f0bfeaa8Sopenharmony_ci return purgObj->dataPtr; 399f0bfeaa8Sopenharmony_ci} 400f0bfeaa8Sopenharmony_ci 401f0bfeaa8Sopenharmony_cisize_t PurgMemGetContentSize(struct PurgMem *purgObj) 402f0bfeaa8Sopenharmony_ci{ 403f0bfeaa8Sopenharmony_ci if (!IsPurgMemPtrValid(purgObj)) { 404f0bfeaa8Sopenharmony_ci PM_HILOG_ERROR_C(LOG_CORE, "%{public}s: para is invalid", __func__); 405f0bfeaa8Sopenharmony_ci return 0; 406f0bfeaa8Sopenharmony_ci } 407f0bfeaa8Sopenharmony_ci return purgObj->dataSizeInput; 408f0bfeaa8Sopenharmony_ci} 409f0bfeaa8Sopenharmony_ci 410f0bfeaa8Sopenharmony_cibool PurgMemAppendModify(struct PurgMem *purgObj, PurgMemModifyFunc func, void *funcPara) 411f0bfeaa8Sopenharmony_ci{ 412f0bfeaa8Sopenharmony_ci IF_NULL_LOG_ACTION(func, "input func is NULL", return true); 413f0bfeaa8Sopenharmony_ci IF_NULL_LOG_ACTION(purgObj, "input purgObj is NULL", return false); 414f0bfeaa8Sopenharmony_ci /* apply modify */ 415f0bfeaa8Sopenharmony_ci bool succ = func(purgObj->dataPtr, purgObj->dataSizeInput, funcPara); 416f0bfeaa8Sopenharmony_ci if (!succ) { 417f0bfeaa8Sopenharmony_ci return false; 418f0bfeaa8Sopenharmony_ci } 419f0bfeaa8Sopenharmony_ci struct PurgMemBuilder *builder = PurgMemBuilderCreate(func, funcPara, NULL); 420f0bfeaa8Sopenharmony_ci IF_NULL_LOG_ACTION(builder, "PurgMemBuilderCreate fail", return false); 421f0bfeaa8Sopenharmony_ci 422f0bfeaa8Sopenharmony_ci if (purgObj->builder == NULL) { /* PurgMemObj has no builder previous */ 423f0bfeaa8Sopenharmony_ci purgObj->builder = builder; 424f0bfeaa8Sopenharmony_ci return true; 425f0bfeaa8Sopenharmony_ci } 426f0bfeaa8Sopenharmony_ci return PurgMemBuilderAppendBuilder(purgObj->builder, builder); 427f0bfeaa8Sopenharmony_ci} 428f0bfeaa8Sopenharmony_ci 429f0bfeaa8Sopenharmony_cistatic bool IsPurged(struct PurgMem *purgObj) 430f0bfeaa8Sopenharmony_ci{ 431f0bfeaa8Sopenharmony_ci /* first access, return true means purged */ 432f0bfeaa8Sopenharmony_ci if (purgObj->buildDataCount == 0) { 433f0bfeaa8Sopenharmony_ci PM_HILOG_INFO_C(LOG_CORE, "%{public}s, has never built, return true", __func__); 434f0bfeaa8Sopenharmony_ci return true; 435f0bfeaa8Sopenharmony_ci } 436f0bfeaa8Sopenharmony_ci return !UxpteIsPresent(purgObj->uxPageTable, (uint64_t)(purgObj->dataPtr), purgObj->dataSizeInput); 437f0bfeaa8Sopenharmony_ci} 438f0bfeaa8Sopenharmony_ci 439f0bfeaa8Sopenharmony_cistatic int TypeCast(void) 440f0bfeaa8Sopenharmony_ci{ 441f0bfeaa8Sopenharmony_ci unsigned int utype = MAP_ANONYMOUS; 442f0bfeaa8Sopenharmony_ci utype |= (UxpteIsEnabled() ? MAP_PURGEABLE : MAP_PRIVATE); 443f0bfeaa8Sopenharmony_ci int type = (int) utype; 444f0bfeaa8Sopenharmony_ci return type; 445f0bfeaa8Sopenharmony_ci}