• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <sys/mman.h> /* mmap */
17 
18 #include "securec.h"
19 #include "pm_util.h"
20 #include "pm_state_c.h"
21 #include "pm_smartptr_util.h"
22 #include "pm_log.h"
23 
24 #include "purgeable_mem.h"
25 
26 namespace OHOS {
27 namespace PurgeableMem {
28 #ifdef LOG_TAG
29 #undef LOG_TAG
30 #endif
31 #define LOG_TAG "PurgeableMem"
32 
RoundUp(size_t val,size_t align)33 static inline size_t RoundUp(size_t val, size_t align)
34 {
35     if (align == 0) {
36         return val;
37     }
38     return ((val + align - 1) / align) * align;
39 }
40 
PurgeableMem(size_t dataSize,std::unique_ptr<PurgeableMemBuilder> builder)41 PurgeableMem::PurgeableMem(size_t dataSize, std::unique_ptr<PurgeableMemBuilder> builder)
42 {
43     dataPtr_ = nullptr;
44     builder_ = nullptr;
45     pageTable_ = nullptr;
46     buildDataCount_ = 0;
47 
48     if (dataSize == 0) {
49         return;
50     }
51     dataSizeInput_ = dataSize;
52     IF_NULL_LOG_ACTION(builder, "%{public}s: input builder nullptr", return);
53 
54     CreatePurgeableData_();
55     builder_ = std::move(builder);
56     PM_HILOG_DEBUG(LOG_CORE, "%{public}s init succ. %{public}s", __func__, ToString().c_str());
57 }
58 
~PurgeableMem()59 PurgeableMem::~PurgeableMem()
60 {
61     PM_HILOG_DEBUG(LOG_CORE, "%{public}s %{public}s", __func__, ToString().c_str());
62     if (dataPtr_) {
63         if (munmap(dataPtr_, RoundUp(dataSizeInput_, PAGE_SIZE)) != 0) {
64             PM_HILOG_ERROR(LOG_CORE, "%{public}s: munmap dataPtr fail", __func__);
65         } else {
66             if (UxpteIsEnabled() && !IsPurged()) {
67                 PM_HILOG_ERROR(LOG_CORE, "%{public}s: munmap dataPtr succ, but uxpte present", __func__);
68             }
69             dataPtr_ = nullptr;
70         }
71     }
72     builder_.reset();
73     pageTable_.reset();
74 }
75 
IsPurged()76 bool PurgeableMem::IsPurged()
77 {
78     IF_NULL_LOG_ACTION(pageTable_, "pageTable_ is nullptrin BeginWrite", return false);
79     return !(pageTable_->CheckPresent((uint64_t)dataPtr_, dataSizeInput_));
80 }
81 
CreatePurgeableData_()82 bool PurgeableMem::CreatePurgeableData_()
83 {
84     PM_HILOG_DEBUG(LOG_CORE, "%{public}s", __func__);
85     pageTable_ = nullptr;
86     size_t size = RoundUp(dataSizeInput_, PAGE_SIZE);
87     unsigned int utype = MAP_ANONYMOUS;
88     utype |= (UxpteIsEnabled() ? MAP_PURGEABLE : MAP_PRIVATE);
89     int type = static_cast<int>(utype);
90 
91     dataPtr_ = mmap(nullptr, size, PROT_READ | PROT_WRITE, type, -1, 0);
92     if (dataPtr_ == MAP_FAILED) {
93         PM_HILOG_ERROR(LOG_CORE, "%{public}s: mmap fail", __func__);
94         dataPtr_ = nullptr;
95         return false;
96     }
97     MAKE_UNIQUE(pageTable_, UxPageTable, "constructor uxpt make_unique fail", return false, (uint64_t)dataPtr_, size);
98     return true;
99 }
100 
Pin()101 bool PurgeableMem::Pin()
102 {
103     IF_NULL_LOG_ACTION(pageTable_, "pageTable_ is nullptrin BeginWrite", return false);
104     pageTable_->GetUxpte((uint64_t)dataPtr_, dataSizeInput_);
105     return true;
106 }
107 
Unpin()108 bool PurgeableMem::Unpin()
109 {
110     IF_NULL_LOG_ACTION(pageTable_, "pageTable_ is nullptrin BeginWrite", return false);
111     pageTable_->PutUxpte((uint64_t)dataPtr_, dataSizeInput_);
112     return true;
113 }
114 
AfterRebuildSucc()115 void PurgeableMem::AfterRebuildSucc()
116 {
117 }
118 
GetPinStatus() const119 int PurgeableMem::GetPinStatus() const
120 {
121     return 0;
122 }
123 
ResizeData(size_t newSize)124 void PurgeableMem::ResizeData(size_t newSize)
125 {
126     if (newSize <= 0) {
127         return;
128     }
129     if (dataPtr_) {
130         if (munmap(dataPtr_, RoundUp(dataSizeInput_, PAGE_SIZE)) != 0) {
131             PM_HILOG_ERROR(LOG_CORE, "%{public}s: munmap dataPtr fail", __func__);
132         } else {
133             dataPtr_ = nullptr;
134         }
135     }
136     dataSizeInput_ = newSize;
137     CreatePurgeableData_();
138 }
139 
ToString() const140 inline std::string PurgeableMem::ToString() const
141 {
142     std::string dataptrStr = dataPtr_ ? std::to_string((unsigned long long)dataPtr_) : "0";
143     std::string pageTableStr = pageTable_ ? pageTable_->ToString() : "0";
144     return "dataAddr:" + dataptrStr + " dataSizeInput:" + std::to_string(dataSizeInput_) +
145         " " + pageTableStr;
146 }
147 } /* namespace PurgeableMem */
148 } /* namespace OHOS */
149