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 #include "host-common/HostmemIdMapping.h"
15 
16 #include <utility>
17 
18 using android::base::ManagedDescriptor;
19 
20 namespace android {
21 namespace emulation {
22 
23 using Id = uint64_t;
24 
25 // static
26 const Id HostmemIdMapping::kInvalidHostmemId = 0;
27 
sMapping()28 static HostmemIdMapping* sMapping() {
29     static HostmemIdMapping* s = new HostmemIdMapping;
30     return s;
31 }
32 
33 // static
get()34 HostmemIdMapping* HostmemIdMapping::get() {
35     return sMapping();
36 }
37 
38 // TODO: Add registerHostmemFixed version that takes a predetermined id,
39 // for snapshots
add(const struct MemEntry * entry)40 Id HostmemIdMapping::add(const struct MemEntry *entry) {
41     if (entry->hva == 0 || entry->size == 0) return kInvalidHostmemId;
42 
43     Id wantedId;
44 
45     if (entry->register_fixed) {
46         wantedId = entry->fixed_id;
47         mCurrentId = wantedId + 1;
48     } else {
49         wantedId = mCurrentId++;
50     }
51 
52     HostmemIdMapping::Entry hostmem_entry;
53     hostmem_entry.id = wantedId;
54     hostmem_entry.hva = entry->hva;
55     hostmem_entry.size = entry->size;
56     hostmem_entry.caching = entry->caching;
57     mEntries.set(wantedId, hostmem_entry);
58     return wantedId;
59 }
60 
remove(Id id)61 void HostmemIdMapping::remove(Id id) {
62     mEntries.erase(id);
63 }
64 
addMapping(Id id,const struct MemEntry * entry)65 void HostmemIdMapping::addMapping(Id id, const struct MemEntry *entry) {
66     HostmemIdMapping::Entry hostmem_entry;
67     hostmem_entry.id = id;
68     hostmem_entry.hva = entry->hva;
69     hostmem_entry.size = entry->size;
70     hostmem_entry.caching = entry->caching;
71     mEntries.set(id, hostmem_entry);
72 }
73 
addDescriptorInfo(Id id,ManagedDescriptor descriptor,uint32_t handleType,uint32_t caching,std::optional<VulkanInfo> vulkanInfoOpt)74 void HostmemIdMapping::addDescriptorInfo(Id id, ManagedDescriptor descriptor,
75                                          uint32_t handleType, uint32_t caching,
76                                          std::optional<VulkanInfo> vulkanInfoOpt) {
77     struct ManagedDescriptorInfo info =
78         {
79             .descriptor = std::move(descriptor),
80             .handleType = handleType,
81             .caching = caching,
82             .vulkanInfoOpt = std::move(vulkanInfoOpt),
83         };
84 
85 
86     mDescriptorInfos.insert(std::make_pair(id, std::move(info)));
87 }
88 
removeDescriptorInfo(Id id)89 std::optional<ManagedDescriptorInfo> HostmemIdMapping::removeDescriptorInfo(Id id) {
90     auto found = mDescriptorInfos.find(id);
91     if (found != mDescriptorInfos.end()) {
92         std::optional<ManagedDescriptorInfo> ret = std::move(found->second);
93         mDescriptorInfos.erase(found);
94         return ret;
95     }
96 
97     return std::nullopt;
98 }
99 
get(Id id) const100 HostmemIdMapping::Entry HostmemIdMapping::get(Id id) const {
101     const HostmemIdMapping::Entry badEntry {
102         kInvalidHostmemId, 0, 0,
103     };
104 
105     if (kInvalidHostmemId == id) return badEntry;
106 
107     auto entry = mEntries.get(id);
108 
109     if (!entry) return badEntry;
110 
111     return *entry;
112 }
113 
clear()114 void HostmemIdMapping::clear() {
115     mEntries.clear();
116 }
117 
118 } // namespace android
119 } // namespace emulation
120 
121 // C interface for use with vm operations
122 extern "C" {
123 
android_emulation_hostmem_register(const struct MemEntry * entry)124 uint64_t android_emulation_hostmem_register(const struct MemEntry *entry) {
125     return static_cast<uint64_t>(
126         android::emulation::HostmemIdMapping::get()->add(entry));
127 }
128 
android_emulation_hostmem_unregister(uint64_t id)129 void android_emulation_hostmem_unregister(uint64_t id) {
130     android::emulation::HostmemIdMapping::get()->remove(id);
131 }
132 
android_emulation_hostmem_get_info(uint64_t id)133 HostmemEntry android_emulation_hostmem_get_info(uint64_t id) {
134     return static_cast<HostmemEntry>(
135         android::emulation::HostmemIdMapping::get()->get(id));
136 }
137 
138 } // extern "C"
139