1 // Copyright 2018 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 #ifndef ANDROID_INCLUDE_HARDWARE_GOLDFISH_ADDRESS_SPACE_H
16 #define ANDROID_INCLUDE_HARDWARE_GOLDFISH_ADDRESS_SPACE_H
17 
18 #include <inttypes.h>
19 #include <stddef.h>
20 
21 #ifdef __Fuchsia__
22 #include <fuchsia/hardware/goldfish/llcpp/fidl.h>
23 #endif
24 
25 class GoldfishAddressSpaceBlock;
26 class GoldfishAddressSpaceHostMemoryAllocator;
27 
28 #ifdef HOST_BUILD
29 
30 namespace android {
31 
32 class HostAddressSpaceDevice;
33 
34 } // namespace android
35 
36 #endif
37 
38 #if defined(__Fuchsia__)
39     typedef void* address_space_handle_t;
40 #elif defined(HOST_BUILD)
41     typedef uint32_t address_space_handle_t;
42 #else
43     typedef int address_space_handle_t;
44 #endif
45 
46 enum GoldfishAddressSpaceSubdeviceType {
47     NoSubdevice = -1,
48     Graphics = 0,
49     Media = 1,
50     HostMemoryAllocator = 5,
51     SharedSlotsHostMemoryAllocator = 6,
52     VirtioGpuGraphics = 10,
53 };
54 
55 class GoldfishAddressSpaceBlockProvider {
56 public:
57     GoldfishAddressSpaceBlockProvider(GoldfishAddressSpaceSubdeviceType subdevice);
58     ~GoldfishAddressSpaceBlockProvider();
59 
60 private:
61     GoldfishAddressSpaceBlockProvider(const GoldfishAddressSpaceBlockProvider &rhs);
62     GoldfishAddressSpaceBlockProvider &operator=(const GoldfishAddressSpaceBlockProvider &rhs);
63 
64     bool is_opened() const;
65     void close();
66     address_space_handle_t release();
67     static void closeHandle(address_space_handle_t handle);
68 
69 #ifdef __Fuchsia__
70     std::unique_ptr<
71         llcpp::fuchsia::hardware::goldfish::AddressSpaceDevice::SyncClient>
72         m_device;
73     std::unique_ptr<
74         llcpp::fuchsia::hardware::goldfish::AddressSpaceChildDriver::SyncClient>
75         m_child_driver;
76 #else // __Fuchsia__
77     address_space_handle_t m_handle;
78 #endif // !__Fuchsia__
79 
80     friend class GoldfishAddressSpaceBlock;
81     friend class GoldfishAddressSpaceHostMemoryAllocator;
82 };
83 
84 class GoldfishAddressSpaceBlock {
85 public:
86     GoldfishAddressSpaceBlock();
87     ~GoldfishAddressSpaceBlock();
88 
89     bool allocate(GoldfishAddressSpaceBlockProvider *provider, size_t size);
90     bool claimShared(GoldfishAddressSpaceBlockProvider *provider, uint64_t offset, uint64_t size);
91     uint64_t physAddr() const;
92     uint64_t hostAddr() const;
offset()93     uint64_t offset() const { return m_offset; }
size()94     size_t size() const { return m_size; }
95     void *mmap(uint64_t opaque);
96     void *guestPtr() const;
97     void replace(GoldfishAddressSpaceBlock *other);
98     void release();
99     static int memoryMap(void *addr, size_t len, address_space_handle_t fd, uint64_t off, void** dst);
100     static void memoryUnmap(void *ptr, size_t size);
101 
102 private:
103     void destroy();
104     GoldfishAddressSpaceBlock &operator=(const GoldfishAddressSpaceBlock &);
105 
106 #ifdef __Fuchsia__
107     llcpp::fuchsia::hardware::goldfish::AddressSpaceChildDriver::SyncClient*
108         m_driver;
109     uint32_t  m_vmo;
110 #else // __Fuchsia__
111     address_space_handle_t m_handle;
112 #endif // !__Fuchsia__
113 
114     void     *m_mmaped_ptr;
115     uint64_t  m_phys_addr;
116     uint64_t  m_host_addr;
117     uint64_t  m_offset;
118     uint64_t  m_size;
119     bool      m_is_shared_mapping;
120 };
121 
122 class GoldfishAddressSpaceHostMemoryAllocator {
123 public:
124     GoldfishAddressSpaceHostMemoryAllocator(bool useSharedSlots);
125 
126     long hostMalloc(GoldfishAddressSpaceBlock *block, size_t size);
127     void hostFree(GoldfishAddressSpaceBlock *block);
128 
129     bool is_opened() const;
release()130     address_space_handle_t release() { return m_provider.release(); }
closeHandle(address_space_handle_t handle)131     static void closeHandle(address_space_handle_t handle) { GoldfishAddressSpaceBlockProvider::closeHandle(handle); }
132 
133 private:
134     GoldfishAddressSpaceBlockProvider m_provider;
135     bool                              m_useSharedSlots;
136 };
137 
138 // Convenience functions that run address space driver api without wrapping in
139 // a class. Useful for when a client wants to manage the driver handle directly
140 // (e.g., mmaping() more than one region associated with a single handle will
141 // require different lifetime expectations versus GoldfishAddressSpaceBlock).
142 
143 // We also expose the ping info struct that is shared between host and guest.
144 struct address_space_ping {
145     uint64_t offset;
146     uint64_t size;
147     uint64_t metadata;
148     uint32_t version;
149     uint32_t wait_fd;
150     uint32_t wait_flags;
151     uint32_t direction;
152 };
153 
154 address_space_handle_t goldfish_address_space_open();
155 void goldfish_address_space_close(address_space_handle_t);
156 
157 bool goldfish_address_space_allocate(
158     address_space_handle_t, size_t size, uint64_t* phys_addr, uint64_t* offset);
159 bool goldfish_address_space_free(
160     address_space_handle_t, uint64_t offset);
161 
162 bool goldfish_address_space_claim_shared(
163     address_space_handle_t, uint64_t offset, uint64_t size);
164 bool goldfish_address_space_unclaim_shared(
165     address_space_handle_t, uint64_t offset);
166 
167 // pgoff is the offset into the page to return in the result
168 void* goldfish_address_space_map(
169     address_space_handle_t, uint64_t offset, uint64_t size, uint64_t pgoff = 0);
170 void goldfish_address_space_unmap(void* ptr, uint64_t size);
171 
172 bool goldfish_address_space_set_subdevice_type(address_space_handle_t, GoldfishAddressSpaceSubdeviceType type, address_space_handle_t*);
173 bool goldfish_address_space_ping(address_space_handle_t, struct address_space_ping*);
174 
175 // virtio-gpu version
176 
177 struct address_space_virtgpu_hostmem_info {
178     uint32_t id;
179     uint32_t bo;
180     void* ptr;
181 };
182 
183 struct address_space_virtgpu_info {
184     int fd;
185     uint32_t resp_bo;
186     uint32_t resp_resid;
187     void* resp_mapped_ptr;
188 };
189 
190 address_space_handle_t virtgpu_address_space_open();
191 void virtgpu_address_space_close(address_space_handle_t);
192 
193 // Ping with no response
194 bool virtgpu_address_space_ping(address_space_handle_t, struct address_space_ping*);
195 
196 bool virtgpu_address_space_create_context_with_subdevice(
197     address_space_handle_t,
198     uint32_t subdevice_type,
199     struct address_space_virtgpu_info* info_out);
200 
201 bool virtgpu_address_space_allocate_hostmem(
202     address_space_handle_t fd,
203     size_t size,
204     uint64_t hostmem_id,
205     struct address_space_virtgpu_hostmem_info* hostmem_info_out);
206 
207 // Ping with response
208 bool virtgpu_address_space_ping_with_response(
209     struct address_space_virtgpu_info* info,
210     struct address_space_ping* ping);
211 
212 // typedef/struct to abstract over goldfish vs virtio-gpu implementations
213 typedef address_space_handle_t (*address_space_open_t)(void);
214 typedef void (*address_space_close_t)(address_space_handle_t);
215 
216 typedef bool (*address_space_allocate_t)(
217     address_space_handle_t, size_t size, uint64_t* phys_addr, uint64_t* offset);
218 typedef bool (*address_space_free_t)(
219     address_space_handle_t, uint64_t offset);
220 
221 typedef bool (*address_space_claim_shared_t)(
222     address_space_handle_t, uint64_t offset, uint64_t size);
223 typedef bool (*address_space_unclaim_shared_t)(
224     address_space_handle_t, uint64_t offset);
225 
226 // pgoff is the offset into the page to return in the result
227 typedef void* (*address_space_map_t)(
228     address_space_handle_t, uint64_t offset, uint64_t size, uint64_t pgoff);
229 typedef void (*address_space_unmap_t)(void* ptr, uint64_t size);
230 
231 typedef bool (*address_space_set_subdevice_type_t)(
232     address_space_handle_t, GoldfishAddressSpaceSubdeviceType type, address_space_handle_t*);
233 typedef bool (*address_space_ping_t)(
234     address_space_handle_t, struct address_space_ping*);
235 
236 // Specific to virtio-gpu
237 typedef bool (*address_space_create_context_with_subdevice_t)(
238     address_space_handle_t,
239     uint32_t subdevice_type,
240     struct address_space_virtgpu_info* info_out);
241 
242 typedef bool (*address_space_allocate_hostmem_t)(
243     address_space_handle_t fd,
244     size_t size,
245     uint64_t hostmem_id,
246     struct address_space_virtgpu_hostmem_info* hostmem_info_out);
247 
248 typedef bool (*address_space_ping_with_response_t)(
249     struct address_space_virtgpu_info* info,
250     struct address_space_ping* ping);
251 
252 struct address_space_ops {
253     address_space_open_t open;
254     address_space_close_t close;
255     address_space_claim_shared_t claim_shared;
256     address_space_unclaim_shared_t unclaim_shared;
257     address_space_map_t map;
258     address_space_unmap_t unmap;
259     address_space_set_subdevice_type_t set_subdevice_type;
260     address_space_ping_t ping;
261     address_space_create_context_with_subdevice_t create_context_with_subdevice;
262     address_space_allocate_hostmem_t allocate_hostmem;
263     address_space_ping_with_response_t ping_with_response;
264 };
265 
266 #endif  // #ifndef ANDROID_INCLUDE_HARDWARE_GOLDFISH_ADDRESS_SPACE_H
267