OLD | NEW |
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/globals.h" | 5 #include "vm/globals.h" |
6 #if defined(HOST_OS_FUCHSIA) | 6 #if defined(HOST_OS_FUCHSIA) |
7 | 7 |
8 #include "vm/virtual_memory.h" | 8 #include "vm/virtual_memory.h" |
9 | 9 |
10 #include <magenta/process.h> | 10 #include <magenta/process.h> |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
83 } | 83 } |
84 #endif | 84 #endif |
85 LOG_INFO("AddVmar(%d, %lx, %ld) at index = %ld\n", vmar, addr, size, idx); | 85 LOG_INFO("AddVmar(%d, %lx, %ld) at index = %ld\n", vmar, addr, size, idx); |
86 VmarListElement new_mapping; | 86 VmarListElement new_mapping; |
87 new_mapping.vmar = vmar; | 87 new_mapping.vmar = vmar; |
88 new_mapping.addr = addr; | 88 new_mapping.addr = addr; |
89 new_mapping.size = size; | 89 new_mapping.size = size; |
90 vmar_array_.InsertAt(idx, new_mapping); | 90 vmar_array_.InsertAt(idx, new_mapping); |
91 } | 91 } |
92 | 92 |
93 | |
94 intptr_t VmarList::LookupVmarIndexLocked(uword addr) { | 93 intptr_t VmarList::LookupVmarIndexLocked(uword addr) { |
95 // Binary search for the vmar containing addr. | 94 // Binary search for the vmar containing addr. |
96 intptr_t imin = 0; | 95 intptr_t imin = 0; |
97 intptr_t imax = vmar_array_.length(); | 96 intptr_t imax = vmar_array_.length(); |
98 while (imax >= imin) { | 97 while (imax >= imin) { |
99 const intptr_t imid = ((imax - imin) / 2) + imin; | 98 const intptr_t imid = ((imax - imin) / 2) + imin; |
100 const VmarListElement& mapping = vmar_array_.At(imid); | 99 const VmarListElement& mapping = vmar_array_.At(imid); |
101 if ((mapping.addr + mapping.size) <= addr) { | 100 if ((mapping.addr + mapping.size) <= addr) { |
102 imin = imid + 1; | 101 imin = imid + 1; |
103 } else if (mapping.addr > addr) { | 102 } else if (mapping.addr > addr) { |
104 imax = imid - 1; | 103 imax = imid - 1; |
105 } else { | 104 } else { |
106 return imid; | 105 return imid; |
107 } | 106 } |
108 } | 107 } |
109 return -1; | 108 return -1; |
110 } | 109 } |
111 | 110 |
112 | |
113 mx_handle_t VmarList::LookupVmar(uword addr) { | 111 mx_handle_t VmarList::LookupVmar(uword addr) { |
114 MutexLocker ml(vmar_array_lock_); | 112 MutexLocker ml(vmar_array_lock_); |
115 LOG_INFO("LookupVmar(%lx)\n", addr); | 113 LOG_INFO("LookupVmar(%lx)\n", addr); |
116 const intptr_t idx = LookupVmarIndexLocked(addr); | 114 const intptr_t idx = LookupVmarIndexLocked(addr); |
117 if (idx == -1) { | 115 if (idx == -1) { |
118 LOG_ERR("LookupVmar(%lx) NOT FOUND\n", addr); | 116 LOG_ERR("LookupVmar(%lx) NOT FOUND\n", addr); |
119 return MX_HANDLE_INVALID; | 117 return MX_HANDLE_INVALID; |
120 } | 118 } |
121 LOG_INFO("LookupVmar(%lx) found at %ld\n", addr, idx); | 119 LOG_INFO("LookupVmar(%lx) found at %ld\n", addr, idx); |
122 return vmar_array_[idx].vmar; | 120 return vmar_array_[idx].vmar; |
123 } | 121 } |
124 | 122 |
125 | |
126 void VmarList::RemoveVmar(uword addr) { | 123 void VmarList::RemoveVmar(uword addr) { |
127 MutexLocker ml(vmar_array_lock_); | 124 MutexLocker ml(vmar_array_lock_); |
128 LOG_INFO("RemoveVmar(%lx)\n", addr); | 125 LOG_INFO("RemoveVmar(%lx)\n", addr); |
129 const intptr_t idx = LookupVmarIndexLocked(addr); | 126 const intptr_t idx = LookupVmarIndexLocked(addr); |
130 ASSERT(idx != -1); | 127 ASSERT(idx != -1); |
131 #if defined(DEBUG) | 128 #if defined(DEBUG) |
132 mx_handle_t vmar = vmar_array_[idx].vmar; | 129 mx_handle_t vmar = vmar_array_[idx].vmar; |
133 #endif | 130 #endif |
134 // Swap idx to the end, and then RemoveLast() | 131 // Swap idx to the end, and then RemoveLast() |
135 const intptr_t length = vmar_array_.length(); | 132 const intptr_t length = vmar_array_.length(); |
136 for (intptr_t i = idx; i < length - 1; i++) { | 133 for (intptr_t i = idx; i < length - 1; i++) { |
137 vmar_array_.Swap(i, i + 1); | 134 vmar_array_.Swap(i, i + 1); |
138 } | 135 } |
139 #if defined(DEBUG) | 136 #if defined(DEBUG) |
140 const VmarListElement& mapping = vmar_array_.Last(); | 137 const VmarListElement& mapping = vmar_array_.Last(); |
141 ASSERT(mapping.vmar == vmar); | 138 ASSERT(mapping.vmar == vmar); |
142 #endif | 139 #endif |
143 vmar_array_.RemoveLast(); | 140 vmar_array_.RemoveLast(); |
144 } | 141 } |
145 | 142 |
146 | |
147 uword VirtualMemory::page_size_ = 0; | 143 uword VirtualMemory::page_size_ = 0; |
148 | 144 |
149 | |
150 void VirtualMemory::InitOnce() { | 145 void VirtualMemory::InitOnce() { |
151 page_size_ = getpagesize(); | 146 page_size_ = getpagesize(); |
152 } | 147 } |
153 | 148 |
154 | |
155 VirtualMemory* VirtualMemory::ReserveInternal(intptr_t size) { | 149 VirtualMemory* VirtualMemory::ReserveInternal(intptr_t size) { |
156 ASSERT(Utils::IsAligned(size, page_size_)); | 150 ASSERT(Utils::IsAligned(size, page_size_)); |
157 mx_handle_t vmar = MX_HANDLE_INVALID; | 151 mx_handle_t vmar = MX_HANDLE_INVALID; |
158 uword addr = 0; | 152 uword addr = 0; |
159 const uint32_t flags = MX_VM_FLAG_COMPACT | MX_VM_FLAG_CAN_MAP_SPECIFIC | | 153 const uint32_t flags = MX_VM_FLAG_COMPACT | MX_VM_FLAG_CAN_MAP_SPECIFIC | |
160 MX_VM_FLAG_CAN_MAP_READ | MX_VM_FLAG_CAN_MAP_WRITE | | 154 MX_VM_FLAG_CAN_MAP_READ | MX_VM_FLAG_CAN_MAP_WRITE | |
161 MX_VM_FLAG_CAN_MAP_EXECUTE; | 155 MX_VM_FLAG_CAN_MAP_EXECUTE; |
162 mx_status_t status = | 156 mx_status_t status = |
163 mx_vmar_allocate(mx_vmar_root_self(), 0, size, flags, &vmar, &addr); | 157 mx_vmar_allocate(mx_vmar_root_self(), 0, size, flags, &vmar, &addr); |
164 if (status != MX_OK) { | 158 if (status != MX_OK) { |
165 LOG_ERR("mx_vmar_allocate(size = %ld) failed: %s\n", size, | 159 LOG_ERR("mx_vmar_allocate(size = %ld) failed: %s\n", size, |
166 mx_status_get_string(status)); | 160 mx_status_get_string(status)); |
167 return NULL; | 161 return NULL; |
168 } | 162 } |
169 VmarList::AddVmar(vmar, addr, size); | 163 VmarList::AddVmar(vmar, addr, size); |
170 MemoryRegion region(reinterpret_cast<void*>(addr), size); | 164 MemoryRegion region(reinterpret_cast<void*>(addr), size); |
171 return new VirtualMemory(region, vmar); | 165 return new VirtualMemory(region, vmar); |
172 } | 166 } |
173 | 167 |
174 | |
175 VirtualMemory::~VirtualMemory() { | 168 VirtualMemory::~VirtualMemory() { |
176 if (vm_owns_region()) { | 169 if (vm_owns_region()) { |
177 mx_handle_t vmar = static_cast<mx_handle_t>(handle()); | 170 mx_handle_t vmar = static_cast<mx_handle_t>(handle()); |
178 mx_status_t status = mx_vmar_destroy(vmar); | 171 mx_status_t status = mx_vmar_destroy(vmar); |
179 if (status != MX_OK) { | 172 if (status != MX_OK) { |
180 LOG_ERR("mx_vmar_destroy failed: %s\n", mx_status_get_string(status)); | 173 LOG_ERR("mx_vmar_destroy failed: %s\n", mx_status_get_string(status)); |
181 } | 174 } |
182 status = mx_handle_close(vmar); | 175 status = mx_handle_close(vmar); |
183 if (status != MX_OK) { | 176 if (status != MX_OK) { |
184 LOG_ERR("mx_handle_close failed: %s\n", mx_status_get_string(status)); | 177 LOG_ERR("mx_handle_close failed: %s\n", mx_status_get_string(status)); |
185 } | 178 } |
186 VmarList::RemoveVmar(start()); | 179 VmarList::RemoveVmar(start()); |
187 } | 180 } |
188 } | 181 } |
189 | 182 |
190 | |
191 bool VirtualMemory::FreeSubSegment(int32_t handle, | 183 bool VirtualMemory::FreeSubSegment(int32_t handle, |
192 void* address, | 184 void* address, |
193 intptr_t size) { | 185 intptr_t size) { |
194 mx_handle_t vmar = static_cast<mx_handle_t>(handle); | 186 mx_handle_t vmar = static_cast<mx_handle_t>(handle); |
195 mx_status_t status = | 187 mx_status_t status = |
196 mx_vmar_unmap(vmar, reinterpret_cast<uintptr_t>(address), size); | 188 mx_vmar_unmap(vmar, reinterpret_cast<uintptr_t>(address), size); |
197 if (status != MX_OK) { | 189 if (status != MX_OK) { |
198 LOG_ERR("mx_vmar_unmap failed: %s\n", mx_status_get_string(status)); | 190 LOG_ERR("mx_vmar_unmap failed: %s\n", mx_status_get_string(status)); |
199 return false; | 191 return false; |
200 } | 192 } |
201 return true; | 193 return true; |
202 } | 194 } |
203 | 195 |
204 | |
205 bool VirtualMemory::Commit(uword addr, | 196 bool VirtualMemory::Commit(uword addr, |
206 intptr_t size, | 197 intptr_t size, |
207 bool executable, | 198 bool executable, |
208 const char* name) { | 199 const char* name) { |
209 ASSERT(Contains(addr)); | 200 ASSERT(Contains(addr)); |
210 ASSERT(Contains(addr + size) || (addr + size == end())); | 201 ASSERT(Contains(addr + size) || (addr + size == end())); |
211 mx_handle_t vmo = MX_HANDLE_INVALID; | 202 mx_handle_t vmo = MX_HANDLE_INVALID; |
212 mx_status_t status = mx_vmo_create(size, 0u, &vmo); | 203 mx_status_t status = mx_vmo_create(size, 0u, &vmo); |
213 if (status != MX_OK) { | 204 if (status != MX_OK) { |
214 LOG_ERR("mx_vmo_create(%ld) failed: %s\n", size, | 205 LOG_ERR("mx_vmo_create(%ld) failed: %s\n", size, |
(...skipping 23 matching lines...) Expand all Loading... |
238 LOG_ERR("mx_vmar_map: addr != mapped_addr: %lx != %lx\n", addr, | 229 LOG_ERR("mx_vmar_map: addr != mapped_addr: %lx != %lx\n", addr, |
239 mapped_addr); | 230 mapped_addr); |
240 return false; | 231 return false; |
241 } | 232 } |
242 mx_handle_close(vmo); | 233 mx_handle_close(vmo); |
243 LOG_INFO("Commit(%lx, %ld, %s): success\n", addr, size, | 234 LOG_INFO("Commit(%lx, %ld, %s): success\n", addr, size, |
244 executable ? "executable" : ""); | 235 executable ? "executable" : ""); |
245 return true; | 236 return true; |
246 } | 237 } |
247 | 238 |
248 | |
249 bool VirtualMemory::Protect(void* address, intptr_t size, Protection mode) { | 239 bool VirtualMemory::Protect(void* address, intptr_t size, Protection mode) { |
250 ASSERT(Thread::Current()->IsMutatorThread() || | 240 ASSERT(Thread::Current()->IsMutatorThread() || |
251 Isolate::Current()->mutator_thread()->IsAtSafepoint()); | 241 Isolate::Current()->mutator_thread()->IsAtSafepoint()); |
252 const uword start_address = reinterpret_cast<uword>(address); | 242 const uword start_address = reinterpret_cast<uword>(address); |
253 const uword end_address = start_address + size; | 243 const uword end_address = start_address + size; |
254 const uword page_address = Utils::RoundDown(start_address, PageSize()); | 244 const uword page_address = Utils::RoundDown(start_address, PageSize()); |
255 mx_handle_t vmar = VmarList::LookupVmar(page_address); | 245 mx_handle_t vmar = VmarList::LookupVmar(page_address); |
256 ASSERT(vmar != MX_HANDLE_INVALID); | 246 ASSERT(vmar != MX_HANDLE_INVALID); |
257 uint32_t prot = 0; | 247 uint32_t prot = 0; |
258 switch (mode) { | 248 switch (mode) { |
(...skipping 23 matching lines...) Expand all Loading... |
282 return false; | 272 return false; |
283 } | 273 } |
284 LOG_INFO("mx_vmar_protect(%lx, %lx, %x) success\n", page_address, | 274 LOG_INFO("mx_vmar_protect(%lx, %lx, %x) success\n", page_address, |
285 end_address - page_address, prot); | 275 end_address - page_address, prot); |
286 return true; | 276 return true; |
287 } | 277 } |
288 | 278 |
289 } // namespace dart | 279 } // namespace dart |
290 | 280 |
291 #endif // defined(HOST_OS_FUCHSIA) | 281 #endif // defined(HOST_OS_FUCHSIA) |
OLD | NEW |