• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2019 The Android Open Source Project
2 //
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 #include "host-common/address_space_host_memory_allocator.h"
16 #include "host-common/address_space_device.hpp"
17 #include "host-common/vm_operations.h"
18 #include "host-common/crash_reporter.h"
19 #include "base/AlignedBuf.h"
20 
21 namespace android {
22 namespace emulation {
23 
AddressSpaceHostMemoryAllocatorContext(const address_space_device_control_ops * ops)24 AddressSpaceHostMemoryAllocatorContext::AddressSpaceHostMemoryAllocatorContext(
25     const address_space_device_control_ops *ops)
26   : m_ops(ops) {
27 }
28 
~AddressSpaceHostMemoryAllocatorContext()29 AddressSpaceHostMemoryAllocatorContext::~AddressSpaceHostMemoryAllocatorContext() {
30     clear();
31 }
32 
perform(AddressSpaceDevicePingInfo * info)33 void AddressSpaceHostMemoryAllocatorContext::perform(AddressSpaceDevicePingInfo *info) {
34     uint64_t result;
35 
36     switch (static_cast<HostMemoryAllocatorCommand>(info->metadata)) {
37     case HostMemoryAllocatorCommand::Allocate:
38         result = allocate(info);
39         break;
40 
41     case HostMemoryAllocatorCommand::Unallocate:
42         result = unallocate(info);
43         break;
44 
45     default:
46         result = -1;
47         break;
48     }
49 
50     info->metadata = result;
51 }
52 
allocate_impl(const uint64_t phys_addr,const uint64_t size)53 void *AddressSpaceHostMemoryAllocatorContext::allocate_impl(const uint64_t phys_addr,
54                                                             const uint64_t size) {
55 #if defined(__APPLE__) && defined(__arm64__)
56     constexpr uint64_t alignment = 16384;
57 #else
58     constexpr uint64_t alignment = 4096;
59 #endif
60     const uint64_t aligned_size = ((size + alignment - 1) / alignment) * alignment;
61 
62     void *host_ptr = android::aligned_buf_alloc(alignment, aligned_size);
63     if (host_ptr) {
64         auto r = m_paddr2ptr.insert({phys_addr, {host_ptr, aligned_size}});
65         if (r.second) {
66             if (m_ops->add_memory_mapping(phys_addr, host_ptr, aligned_size)) {
67                 return host_ptr;
68             } else {
69                 m_paddr2ptr.erase(r.first);
70                 android::aligned_buf_free(host_ptr);
71                 return nullptr;
72             }
73         } else {
74             android::aligned_buf_free(host_ptr);
75             return nullptr;
76         }
77     } else {
78         return nullptr;
79     }
80 }
81 
allocate(AddressSpaceDevicePingInfo * info)82 uint64_t AddressSpaceHostMemoryAllocatorContext::allocate(AddressSpaceDevicePingInfo *info) {
83     void* host_ptr = allocate_impl(info->phys_addr, info->size);
84     if (host_ptr) {
85         return 0;
86     } else {
87         return -1;
88     }
89 }
90 
unallocate(AddressSpaceDevicePingInfo * info)91 uint64_t AddressSpaceHostMemoryAllocatorContext::unallocate(AddressSpaceDevicePingInfo *info) {
92     const uint64_t phys_addr = info->phys_addr;
93     const auto i = m_paddr2ptr.find(phys_addr);
94     if (i != m_paddr2ptr.end()) {
95         void* host_ptr = i->second.first;
96         const uint64_t size = i->second.second;
97 
98         if (m_ops->remove_memory_mapping(phys_addr, host_ptr, size)) {
99             android::aligned_buf_free(host_ptr);
100             m_paddr2ptr.erase(i);
101             return 0;
102         } else {
103             crashhandler_die("Failed remove a memory mapping {phys_addr=%lx, host_ptr=%p, size=%lu}",
104                              phys_addr, host_ptr, size);
105         }
106     } else {
107         return -1;
108     }
109     return 0;
110 }
111 
getDeviceType() const112 AddressSpaceDeviceType AddressSpaceHostMemoryAllocatorContext::getDeviceType() const {
113     return AddressSpaceDeviceType::HostMemoryAllocator;
114 }
115 
save(base::Stream * stream) const116 void AddressSpaceHostMemoryAllocatorContext::save(base::Stream* stream) const {
117     stream->putBe32(m_paddr2ptr.size());
118 
119     for (const auto &kv : m_paddr2ptr) {
120         const uint64_t phys_addr = kv.first;
121         const uint64_t size = kv.second.second;
122         const void *mem = kv.second.first;
123 
124         stream->putBe64(phys_addr);
125         stream->putBe64(size);
126         stream->write(mem, size);
127     }
128 }
129 
load(base::Stream * stream)130 bool AddressSpaceHostMemoryAllocatorContext::load(base::Stream* stream) {
131     clear();
132 
133     size_t size = stream->getBe32();
134 
135     for (size_t i = 0; i < size; ++i) {
136         uint64_t phys_addr = stream->getBe64();
137         uint64_t size = stream->getBe64();
138         void *mem = allocate_impl(phys_addr, size);
139         if (mem) {
140             if (stream->read(mem, size) != static_cast<ssize_t>(size)) {
141                 return false;
142             }
143         } else {
144             return false;
145         }
146     }
147 
148     return true;
149 }
150 
clear()151 void AddressSpaceHostMemoryAllocatorContext::clear() {
152     for (const auto& kv : m_paddr2ptr) {
153         uint64_t phys_addr = kv.first;
154         void *host_ptr = kv.second.first;
155         size_t size = kv.second.second;
156 
157         if (m_ops->remove_memory_mapping(phys_addr, host_ptr, size)) {
158             android::aligned_buf_free(host_ptr);
159         } else {
160             crashhandler_die("Failed remove a memory mapping {phys_addr=%lx, host_ptr=%p, size=%lu}",
161                              phys_addr, host_ptr, size);
162         }
163     }
164 }
165 
166 }  // namespace emulation
167 }  // namespace android
168