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