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 #pragma once
15 
16 #include <inttypes.h>
17 
18 #include <atomic>
19 #include <mutex>
20 #include <optional>
21 #include <unordered_map>
22 #include <utility>
23 
24 #include "aemu/base/Compiler.h"
25 #include "aemu/base/ManagedDescriptor.hpp"
26 
27 // A global mapping from opaque host memory IDs to host virtual
28 // addresses/sizes.  This is so that the guest doesn't have to know the host
29 // virtual address to be able to map them. However, we do also provide a
30 // mechanism for obtaining the offsets into page for such buffers (as the guest
31 // does need to know those).
32 //
33 // This is currently used only in conjunction with virtio-gpu-next and Vulkan /
34 // address space device, though there are possible other consumers of this, so
35 // it becomes a global object. It exports methods into VmOperations.
36 
37 using android::base::ManagedDescriptor;
38 
39 namespace gfxstream {
40 
41 // Caching types
42 #define MAP_CACHE_MASK 0x0f
43 #define MAP_CACHE_NONE 0x00
44 #define MAP_CACHE_CACHED 0x01
45 #define MAP_CACHE_UNCACHED 0x02
46 #define MAP_CACHE_WC 0x03
47 
48 #define STREAM_MEM_HANDLE_TYPE_OPAQUE_FD 0x1
49 #define STREAM_MEM_HANDLE_TYPE_DMABUF 0x2
50 #define STREAM_MEM_HANDLE_TYPE_OPAQUE_WIN32 0x3
51 #define STREAM_MEM_HANDLE_TYPE_SHM 0x4
52 #define STREAM_MEM_HANDLE_TYPE_ZIRCON 0x5
53 #define STREAM_FENCE_HANDLE_TYPE_OPAQUE_FD 0x6
54 #define STREAM_FENCE_HANDLE_TYPE_SYNC_FD 0x7
55 #define STREAM_FENCE_HANDLE_TYPE_OPAQUE_WIN32 0x8
56 #define STREAM_FENCE_HANDLE_TYPE_ZIRCON 0x9
57 
58 // A struct describing the information about host memory associated
59 // with a host memory id. Used with virtio-gpu-next.
60 struct HostMemInfo {
61     void* addr;
62     uint32_t caching;
63 };
64 
65 struct VulkanInfo {
66     uint32_t memoryIndex;
67     uint8_t deviceUUID[16];
68     uint8_t driverUUID[16];
69 };
70 
71 struct BlobDescriptorInfo {
72     ManagedDescriptor descriptor;
73     uint32_t handleType;
74     uint32_t caching;
75     std::optional<VulkanInfo> vulkanInfoOpt;
76 };
77 
78 struct SyncDescriptorInfo {
79     ManagedDescriptor descriptor;
80     uint32_t handleType;
81 };
82 
83 class ExternalObjectManager {
84    public:
85     ExternalObjectManager() = default;
86 
87     static ExternalObjectManager* get();
88 
89     void addMapping(uint32_t ctx_id, uint64_t blobId, void* addr, uint32_t caching);
90     std::optional<HostMemInfo> removeMapping(uint32_t ctx_id, uint64_t blobId);
91 
92     void addBlobDescriptorInfo(uint32_t ctx_id, uint64_t blobId, ManagedDescriptor descriptor,
93                                uint32_t handleType, uint32_t caching,
94                                std::optional<VulkanInfo> vulkanInfoOpt);
95     std::optional<BlobDescriptorInfo> removeBlobDescriptorInfo(uint32_t ctx_id, uint64_t blobId);
96 
97     void addSyncDescriptorInfo(uint32_t ctx_id, uint64_t syncId, ManagedDescriptor descriptor,
98                                uint32_t handleType);
99     std::optional<SyncDescriptorInfo> removeSyncDescriptorInfo(uint32_t ctx_id, uint64_t syncId);
100 
101    private:
102     // Only for pairs of std::hash-able types for simplicity.
103     // You can of course template this struct to allow other hash functions
104     struct pair_hash {
105         template <class T1, class T2>
operatorpair_hash106         std::size_t operator()(const std::pair<T1, T2>& p) const {
107             auto h1 = std::hash<T1>{}(p.first);
108             auto h2 = std::hash<T2>{}(p.second);
109 
110             // Mainly for demonstration purposes, i.e. works but is overly simple
111             // In the real world, use sth. like boost.hash_combine
112             return h1 ^ h2;
113         }
114     };
115 
116     std::mutex mLock;
117     std::unordered_map<std::pair<uint32_t, uint64_t>, HostMemInfo, pair_hash> mHostMemInfos;
118     std::unordered_map<std::pair<uint32_t, uint64_t>, BlobDescriptorInfo, pair_hash>
119         mBlobDescriptorInfos;
120     std::unordered_map<std::pair<uint32_t, uint64_t>, SyncDescriptorInfo, pair_hash>
121         mSyncDescriptorInfos;
122     DISALLOW_COPY_ASSIGN_AND_MOVE(ExternalObjectManager);
123 };
124 
125 }  // namespace gfxstream
126