• 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 #include "host-common/address_space_device.h"
15 #include "host-common/AddressSpaceService.h"
16 #include "host-common/address_space_graphics.h"
17 #ifndef AEMU_MIN
18 #include "host-common/address_space_host_media.h"
19 #endif
20 #include "host-common/address_space_host_memory_allocator.h"
21 #include "host-common/address_space_shared_slots_host_memory_allocator.h"
22 #include "host-common/vm_operations.h"
23 
24 #include "aemu/base/synchronization/Lock.h"
25 
26 #include <map>
27 #include <unordered_map>
28 #include <memory>
29 
30 using android::base::AutoLock;
31 using android::base::Lock;
32 using android::base::Stream;
33 using android::emulation::asg::AddressSpaceGraphicsContext;
34 
35 using namespace android::emulation;
36 
37 #define AS_DEVICE_DEBUG 0
38 
39 #if AS_DEVICE_DEBUG
40 #define AS_DEVICE_DPRINT(fmt,...) fprintf(stderr, "%s:%d " fmt "\n", __func__, __LINE__, ##__VA_ARGS__);
41 #else
42 #define AS_DEVICE_DPRINT(fmt,...)
43 #endif
44 
45 const QAndroidVmOperations* sVmOps = nullptr;
46 
47 namespace {
48 
49 class AddressSpaceDeviceState {
50 public:
51     AddressSpaceDeviceState() = default;
52     ~AddressSpaceDeviceState() = default;
53 
genHandle()54     uint32_t genHandle() {
55         AutoLock lock(mContextsLock);
56 
57         auto res = mHandleIndex;
58 
59         if (!res) {
60             ++res;
61             mHandleIndex += 2;
62         } else {
63             ++mHandleIndex;
64         }
65 
66         AS_DEVICE_DPRINT("new handle: %u", res);
67         return res;
68     }
69 
destroyHandle(uint32_t handle)70     void destroyHandle(uint32_t handle) {
71         AS_DEVICE_DPRINT("erase handle: %u", handle);
72 
73         std::unique_ptr<AddressSpaceDeviceContext> context;
74 
75         {
76             AutoLock lock(mContextsLock);
77 
78             auto contextDescriptionIt = mContexts.find(handle);
79             if (contextDescriptionIt == mContexts.end()) return;
80             auto& contextDescription = contextDescriptionIt->second;
81 
82             context = std::move(contextDescription.device_context);
83 
84             mContexts.erase(contextDescriptionIt);
85         }
86 
87         // Destroy `context` without holding the lock.
88     }
89 
tellPingInfo(uint32_t handle,uint64_t gpa)90     void tellPingInfo(uint32_t handle, uint64_t gpa) {
91         AutoLock lock(mContextsLock);
92         auto& contextDesc = mContexts[handle];
93         contextDesc.pingInfo =
94             (AddressSpaceDevicePingInfo*)
95             sVmOps->physicalMemoryGetAddr(gpa);
96         contextDesc.pingInfoGpa = gpa;
97         AS_DEVICE_DPRINT("Ping info: gpa 0x%llx @ %p\n", (unsigned long long)gpa,
98                          contextDesc.pingInfo);
99     }
100 
createInstance(const struct AddressSpaceCreateInfo & create)101     void createInstance(const struct AddressSpaceCreateInfo& create) {
102         AutoLock lock(mContextsLock);
103         auto& contextDesc = mContexts[create.handle];
104         contextDesc.device_context = buildAddressSpaceDeviceContext(create);
105     }
106 
ping(uint32_t handle)107     void ping(uint32_t handle) {
108         AutoLock lock(mContextsLock);
109         auto& contextDesc = mContexts[handle];
110         AddressSpaceDevicePingInfo* pingInfo = contextDesc.pingInfo;
111 
112         const uint64_t phys_addr = pingInfo->phys_addr;
113 
114         AS_DEVICE_DPRINT(
115                 "handle %u data 0x%llx -> %p size %llu meta 0x%llx\n", handle,
116                 (unsigned long long)phys_addr,
117                 sVmOps->physicalMemoryGetAddr(phys_addr),
118                 (unsigned long long)pingInfo->size, (unsigned long long)pingInfo->metadata);
119 
120         AddressSpaceDeviceContext *device_context = contextDesc.device_context.get();
121         if (device_context) {
122             device_context->perform(pingInfo);
123         } else {
124             // The first ioctl establishes the device type
125             struct AddressSpaceCreateInfo create = {0};
126             create.type = static_cast<AddressSpaceDeviceType>(pingInfo->metadata);
127             create.physAddr = phys_addr;
128 
129             contextDesc.device_context = buildAddressSpaceDeviceContext(create);
130             pingInfo->metadata = contextDesc.device_context ? 0 : -1;
131         }
132     }
133 
pingAtHva(uint32_t handle,AddressSpaceDevicePingInfo * pingInfo)134     void pingAtHva(uint32_t handle, AddressSpaceDevicePingInfo* pingInfo) {
135         AutoLock lock(mContextsLock);
136         auto& contextDesc = mContexts[handle];
137 
138         const uint64_t phys_addr = pingInfo->phys_addr;
139 
140         AS_DEVICE_DPRINT(
141                 "handle %u data 0x%llx -> %p size %llu meta 0x%llx\n", handle,
142                 (unsigned long long)phys_addr,
143                 sVmOps->physicalMemoryGetAddr(phys_addr),
144                 (unsigned long long)pingInfo->size, (unsigned long long)pingInfo->metadata);
145 
146         AddressSpaceDeviceContext *device_context = contextDesc.device_context.get();
147         if (device_context) {
148             device_context->perform(pingInfo);
149         } else {
150             struct AddressSpaceCreateInfo create = {0};
151             create.type = static_cast<AddressSpaceDeviceType>(pingInfo->metadata);
152             create.physAddr = phys_addr;
153 
154             contextDesc.device_context = buildAddressSpaceDeviceContext(create);
155             pingInfo->metadata = contextDesc.device_context ? 0 : -1;
156         }
157     }
158 
registerDeallocationCallback(uint64_t gpa,void * context,address_space_device_deallocation_callback_t func)159     void registerDeallocationCallback(uint64_t gpa, void* context, address_space_device_deallocation_callback_t func) {
160         AutoLock lock(mContextsLock);
161         auto& currentCallbacks = mDeallocationCallbacks[gpa];
162 
163         DeallocationCallbackEntry entry = {
164             context,
165             func,
166         };
167 
168         currentCallbacks.push_back(entry);
169     }
170 
runDeallocationCallbacks(uint64_t gpa)171     void runDeallocationCallbacks(uint64_t gpa) {
172         AutoLock lock(mContextsLock);
173 
174         auto it = mDeallocationCallbacks.find(gpa);
175         if (it == mDeallocationCallbacks.end()) return;
176 
177         auto& callbacks = it->second;
178 
179         for (auto& entry: callbacks) {
180             entry.func(entry.context, gpa);
181         }
182 
183         mDeallocationCallbacks.erase(gpa);
184     }
185 
handleToContext(uint32_t handle)186     AddressSpaceDeviceContext* handleToContext(uint32_t handle) {
187         AutoLock lock(mContextsLock);
188         if (mContexts.find(handle) == mContexts.end()) return nullptr;
189 
190         auto& contextDesc = mContexts[handle];
191         return contextDesc.device_context.get();
192     }
193 
hostmemRegister(const struct MemEntry * entry)194     uint64_t hostmemRegister(const struct MemEntry *entry) {
195         return sVmOps->hostmemRegister(entry);
196     }
197 
hostmemUnregister(uint64_t id)198     void hostmemUnregister(uint64_t id) {
199         sVmOps->hostmemUnregister(id);
200     }
201 
save(Stream * stream) const202     void save(Stream* stream) const {
203         // Pre-save
204         for (const auto &kv : mContexts) {
205             const AddressSpaceContextDescription &desc = kv.second;
206             const AddressSpaceDeviceContext *device_context = desc.device_context.get();
207             if (device_context) {
208                 device_context->preSave();
209             }
210         }
211 
212         AddressSpaceGraphicsContext::globalStatePreSave();
213 
214         // Save
215         AddressSpaceSharedSlotsHostMemoryAllocatorContext::globalStateSave(stream);
216         AddressSpaceGraphicsContext::globalStateSave(stream);
217 
218         stream->putBe32(mHandleIndex);
219         stream->putBe32(mContexts.size());
220 
221         for (const auto &kv : mContexts) {
222             const uint32_t handle = kv.first;
223             const AddressSpaceContextDescription &desc = kv.second;
224             const AddressSpaceDeviceContext *device_context = desc.device_context.get();
225 
226             stream->putBe32(handle);
227             stream->putBe64(desc.pingInfoGpa);
228 
229             if (device_context) {
230                 stream->putByte(1);
231                 stream->putBe32(device_context->getDeviceType());
232                 device_context->save(stream);
233             } else {
234                 stream->putByte(0);
235             }
236         }
237 
238         // Post save
239 
240         AddressSpaceGraphicsContext::globalStatePostSave();
241 
242         for (const auto &kv : mContexts) {
243             const AddressSpaceContextDescription &desc = kv.second;
244             const AddressSpaceDeviceContext *device_context = desc.device_context.get();
245             if (device_context) {
246                 device_context->postSave();
247             }
248         }
249     }
250 
setLoadResources(AddressSpaceDeviceLoadResources resources)251     void setLoadResources(AddressSpaceDeviceLoadResources resources) {
252         mLoadResources = std::move(resources);
253     }
254 
load(Stream * stream)255     bool load(Stream* stream) {
256         // First destroy all contexts, because
257         // this can be done while an emulator is running
258         clear();
259 
260         if (!AddressSpaceSharedSlotsHostMemoryAllocatorContext::globalStateLoad(
261                 stream,
262                 get_address_space_device_control_ops(),
263                 get_address_space_device_hw_funcs())) {
264             return false;
265         }
266 
267         asg::AddressSpaceGraphicsContext::init(get_address_space_device_control_ops());
268 
269         if (!AddressSpaceGraphicsContext::globalStateLoad(stream, mLoadResources)) {
270             return false;
271         }
272 
273         const uint32_t handleIndex = stream->getBe32();
274         const size_t size = stream->getBe32();
275 
276         Contexts contexts;
277         for (size_t i = 0; i < size; ++i) {
278             const uint32_t handle = stream->getBe32();
279             const uint64_t pingInfoGpa = stream->getBe64();
280 
281             std::unique_ptr<AddressSpaceDeviceContext> context;
282             switch (stream->getByte()) {
283             case 0:
284                 break;
285 
286             case 1: {
287                 struct AddressSpaceCreateInfo create = {0};
288                 create.type = static_cast<AddressSpaceDeviceType>(stream->getBe32());
289                 create.physAddr = pingInfoGpa;
290                 create.fromSnapshot = true;
291 
292                 context = buildAddressSpaceDeviceContext(create);
293                 if (!context || !context->load(stream)) {
294                     return false;
295                     }
296                 }
297                 break;
298 
299             default:
300                 return false;
301             }
302 
303             auto &desc = contexts[handle];
304             desc.pingInfoGpa = pingInfoGpa;
305             if (desc.pingInfoGpa == ~0ULL) {
306                 fprintf(stderr, "%s: warning: restoring hva-only ping\n", __func__);
307             } else {
308                 desc.pingInfo = (AddressSpaceDevicePingInfo*)
309                     sVmOps->physicalMemoryGetAddr(pingInfoGpa);
310             }
311             desc.device_context = std::move(context);
312         }
313 
314         {
315            AutoLock lock(mContextsLock);
316            mHandleIndex = handleIndex;
317            mContexts = std::move(contexts);
318         }
319 
320         return true;
321     }
322 
clear()323     void clear() {
324         AutoLock lock(mContextsLock);
325         mContexts.clear();
326         AddressSpaceSharedSlotsHostMemoryAllocatorContext::globalStateClear();
327         std::vector<std::pair<uint64_t, uint64_t>> gpasSizesToErase;
328         for (auto& mapping : mMemoryMappings) {
329             auto gpa = mapping.first;
330             auto size = mapping.second.second;
331             gpasSizesToErase.push_back({gpa, size});
332         }
333         for (const auto& gpaSize : gpasSizesToErase) {
334             removeMemoryMappingLocked(gpaSize.first, gpaSize.second);
335         }
336         mMemoryMappings.clear();
337     }
338 
addMemoryMapping(uint64_t gpa,void * ptr,uint64_t size)339     bool addMemoryMapping(uint64_t gpa, void *ptr, uint64_t size) {
340         AutoLock lock(mMemoryMappingsLock);
341         return addMemoryMappingLocked(gpa, ptr, size);
342     }
343 
removeMemoryMapping(uint64_t gpa,uint64_t size)344     bool removeMemoryMapping(uint64_t gpa, uint64_t size) {
345         AutoLock lock(mMemoryMappingsLock);
346         return removeMemoryMappingLocked(gpa, size);
347     }
348 
getHostPtr(uint64_t gpa) const349     void *getHostPtr(uint64_t gpa) const {
350         AutoLock lock(mMemoryMappingsLock);
351         return getHostPtrLocked(gpa);
352     }
353 
354 private:
355     mutable Lock mContextsLock;
356     uint32_t mHandleIndex = 1;
357     typedef std::unordered_map<uint32_t, AddressSpaceContextDescription> Contexts;
358     Contexts mContexts;
359 
buildAddressSpaceDeviceContext(const struct AddressSpaceCreateInfo & create)360     std::unique_ptr<AddressSpaceDeviceContext> buildAddressSpaceDeviceContext(
361         const struct AddressSpaceCreateInfo& create) {
362         typedef std::unique_ptr<AddressSpaceDeviceContext> DeviceContextPtr;
363 
364         switch (create.type) {
365             case AddressSpaceDeviceType::Graphics:
366                 asg::AddressSpaceGraphicsContext::init(get_address_space_device_control_ops());
367                 return DeviceContextPtr(new asg::AddressSpaceGraphicsContext(create));
368 #ifndef AEMU_MIN
369         case AddressSpaceDeviceType::Media:
370             AS_DEVICE_DPRINT("allocating media context");
371             return DeviceContextPtr(
372                 new AddressSpaceHostMediaContext(create, get_address_space_device_control_ops()));
373 #endif
374         case AddressSpaceDeviceType::Sensors:
375             return nullptr;
376         case AddressSpaceDeviceType::Power:
377             return nullptr;
378         case AddressSpaceDeviceType::GenericPipe:
379             return nullptr;
380         case AddressSpaceDeviceType::HostMemoryAllocator:
381             return DeviceContextPtr(new AddressSpaceHostMemoryAllocatorContext(
382                 get_address_space_device_control_ops(),
383                 get_address_space_device_hw_funcs()));
384         case AddressSpaceDeviceType::SharedSlotsHostMemoryAllocator:
385             return DeviceContextPtr(new AddressSpaceSharedSlotsHostMemoryAllocatorContext(
386                 get_address_space_device_control_ops(),
387                 get_address_space_device_hw_funcs()));
388 
389         case AddressSpaceDeviceType::VirtioGpuGraphics:
390             asg::AddressSpaceGraphicsContext::init(get_address_space_device_control_ops());
391             return DeviceContextPtr(new asg::AddressSpaceGraphicsContext(create));
392 
393         default:
394             AS_DEVICE_DPRINT("Bad device type");
395             return nullptr;
396         }
397     }
398 
addMemoryMappingLocked(uint64_t gpa,void * ptr,uint64_t size)399     bool addMemoryMappingLocked(uint64_t gpa, void *ptr, uint64_t size) {
400         if (mMemoryMappings.insert({gpa, {ptr, size}}).second) {
401             sVmOps->mapUserBackedRam(gpa, ptr, size);
402             return true;
403         } else {
404             fprintf(stderr, "%s: failed: hva %p -> gpa [0x%llx 0x%llx]\n", __func__,
405                     ptr,
406                     (unsigned long long)gpa,
407                     (unsigned long long)size);
408             return false;
409         }
410     }
411 
removeMemoryMappingLocked(uint64_t gpa,uint64_t size)412     bool removeMemoryMappingLocked(uint64_t gpa, uint64_t size) {
413         if (mMemoryMappings.erase(gpa) > 0) {
414             sVmOps->unmapUserBackedRam(gpa, size);
415             return true;
416         } else {
417             fprintf(stderr, "%s: failed: gpa [0x%llx 0x%llx]\n", __func__,
418                     (unsigned long long)gpa,
419                     (unsigned long long)size);
420             *(uint32_t*)(123) = 12;
421             return false;
422         }
423     }
424 
getHostPtrLocked(uint64_t gpa) const425     void *getHostPtrLocked(uint64_t gpa) const {
426         auto i = mMemoryMappings.lower_bound(gpa); // i->first >= gpa (or i==end)
427         if ((i != mMemoryMappings.end()) && (i->first == gpa)) {
428             return i->second.first;  // gpa is exactly the beginning of the range
429         } else if (i == mMemoryMappings.begin()) {
430             return nullptr;  // can't '--i', see below
431         } else {
432             --i;
433 
434             if ((i->first + i->second.second) > gpa) {
435                 // move the host ptr by +(gpa-base)
436                 return static_cast<char *>(i->second.first) + (gpa - i->first);
437             } else {
438                 return nullptr;  // the range does not cover gpa
439             }
440         }
441     }
442 
443     mutable Lock mMemoryMappingsLock;
444     std::map<uint64_t, std::pair<void *, uint64_t>> mMemoryMappings;  // do not save/load
445 
446     struct DeallocationCallbackEntry {
447         void* context;
448         address_space_device_deallocation_callback_t func;
449     };
450 
451     std::map<uint64_t, std::vector<DeallocationCallbackEntry>> mDeallocationCallbacks; // do not save/load, users re-register on load
452 
453     // Not saved/loaded. Externally owned resources used during load.
454     std::optional<AddressSpaceDeviceLoadResources> mLoadResources;
455 };
456 
sAddressSpaceDeviceState()457 static AddressSpaceDeviceState* sAddressSpaceDeviceState() {
458     static AddressSpaceDeviceState* s = new AddressSpaceDeviceState;
459     return s;
460 }
461 
sAddressSpaceDeviceGenHandle()462 static uint32_t sAddressSpaceDeviceGenHandle() {
463     return sAddressSpaceDeviceState()->genHandle();
464 }
465 
sAddressSpaceDeviceDestroyHandle(uint32_t handle)466 static void sAddressSpaceDeviceDestroyHandle(uint32_t handle) {
467     sAddressSpaceDeviceState()->destroyHandle(handle);
468 }
469 
sAddressSpaceDeviceCreateInstance(const struct AddressSpaceCreateInfo & create)470 static void sAddressSpaceDeviceCreateInstance(const struct AddressSpaceCreateInfo& create) {
471     sAddressSpaceDeviceState()->createInstance(create);
472 }
473 
sAddressSpaceDeviceTellPingInfo(uint32_t handle,uint64_t gpa)474 static void sAddressSpaceDeviceTellPingInfo(uint32_t handle, uint64_t gpa) {
475     sAddressSpaceDeviceState()->tellPingInfo(handle, gpa);
476 }
477 
sAddressSpaceDevicePing(uint32_t handle)478 static void sAddressSpaceDevicePing(uint32_t handle) {
479     sAddressSpaceDeviceState()->ping(handle);
480 }
481 
sAddressSpaceDeviceAddMemoryMapping(uint64_t gpa,void * ptr,uint64_t size)482 int sAddressSpaceDeviceAddMemoryMapping(uint64_t gpa, void *ptr, uint64_t size) {
483     return sAddressSpaceDeviceState()->addMemoryMapping(gpa, ptr, size) ? 1 : 0;
484 }
485 
sAddressSpaceDeviceRemoveMemoryMapping(uint64_t gpa,void * ptr,uint64_t size)486 int sAddressSpaceDeviceRemoveMemoryMapping(uint64_t gpa, void *ptr, uint64_t size) {
487     (void)ptr; // TODO(lfy): remove arg
488     return sAddressSpaceDeviceState()->removeMemoryMapping(gpa, size) ? 1 : 0;
489 }
490 
sAddressSpaceDeviceGetHostPtr(uint64_t gpa)491 void* sAddressSpaceDeviceGetHostPtr(uint64_t gpa) {
492     return sAddressSpaceDeviceState()->getHostPtr(gpa);
493 }
494 
sAddressSpaceHandleToContext(uint32_t handle)495 static void* sAddressSpaceHandleToContext(uint32_t handle) {
496     return (void*)(sAddressSpaceDeviceState()->handleToContext(handle));
497 }
498 
sAddressSpaceDeviceClear()499 static void sAddressSpaceDeviceClear() {
500     sAddressSpaceDeviceState()->clear();
501 }
502 
sAddressSpaceDeviceHostmemRegister(const struct MemEntry * entry)503 static uint64_t sAddressSpaceDeviceHostmemRegister(const struct MemEntry *entry) {
504     return sAddressSpaceDeviceState()->hostmemRegister(entry);
505 }
506 
sAddressSpaceDeviceHostmemUnregister(uint64_t id)507 static void sAddressSpaceDeviceHostmemUnregister(uint64_t id) {
508     sAddressSpaceDeviceState()->hostmemUnregister(id);
509 }
510 
sAddressSpaceDevicePingAtHva(uint32_t handle,void * hva)511 static void sAddressSpaceDevicePingAtHva(uint32_t handle, void* hva) {
512     sAddressSpaceDeviceState()->pingAtHva(
513         handle, (AddressSpaceDevicePingInfo*)hva);
514 }
515 
sAddressSpaceDeviceRegisterDeallocationCallback(void * context,uint64_t gpa,address_space_device_deallocation_callback_t func)516 static void sAddressSpaceDeviceRegisterDeallocationCallback(
517     void* context, uint64_t gpa, address_space_device_deallocation_callback_t func) {
518     sAddressSpaceDeviceState()->registerDeallocationCallback(gpa, context, func);
519 }
520 
sAddressSpaceDeviceRunDeallocationCallbacks(uint64_t gpa)521 static void sAddressSpaceDeviceRunDeallocationCallbacks(uint64_t gpa) {
522     sAddressSpaceDeviceState()->runDeallocationCallbacks(gpa);
523 }
524 
sAddressSpaceDeviceControlGetHwFuncs()525 static const struct AddressSpaceHwFuncs* sAddressSpaceDeviceControlGetHwFuncs() {
526     return get_address_space_device_hw_funcs();
527 }
528 
529 
530 } // namespace
531 
532 extern "C" {
533 
534 static struct address_space_device_control_ops sAddressSpaceDeviceOps = {
535     &sAddressSpaceDeviceGenHandle,                     // gen_handle
536     &sAddressSpaceDeviceDestroyHandle,                 // destroy_handle
537     &sAddressSpaceDeviceTellPingInfo,                  // tell_ping_info
538     &sAddressSpaceDevicePing,                          // ping
539     &sAddressSpaceDeviceAddMemoryMapping,              // add_memory_mapping
540     &sAddressSpaceDeviceRemoveMemoryMapping,           // remove_memory_mapping
541     &sAddressSpaceDeviceGetHostPtr,                    // get_host_ptr
542     &sAddressSpaceHandleToContext,                     // handle_to_context
543     &sAddressSpaceDeviceClear,                         // clear
544     &sAddressSpaceDeviceHostmemRegister,               // hostmem register
545     &sAddressSpaceDeviceHostmemUnregister,             // hostmem unregister
546     &sAddressSpaceDevicePingAtHva,                     // ping_at_hva
547     &sAddressSpaceDeviceRegisterDeallocationCallback,  // register_deallocation_callback
548     &sAddressSpaceDeviceRunDeallocationCallbacks,      // run_deallocation_callbacks
549     &sAddressSpaceDeviceControlGetHwFuncs,             // control_get_hw_funcs
550     &sAddressSpaceDeviceCreateInstance,                // create_instance
551 };
552 
get_address_space_device_control_ops(void)553 struct address_space_device_control_ops* get_address_space_device_control_ops(void) {
554     return &sAddressSpaceDeviceOps;
555 }
556 
557 static const struct AddressSpaceHwFuncs* sAddressSpaceHwFuncs = nullptr;
558 
address_space_set_hw_funcs(const AddressSpaceHwFuncs * hwFuncs)559 const struct AddressSpaceHwFuncs* address_space_set_hw_funcs(
560         const AddressSpaceHwFuncs* hwFuncs) {
561     const AddressSpaceHwFuncs* result = sAddressSpaceHwFuncs;
562     sAddressSpaceHwFuncs = hwFuncs;
563     return result;
564 }
565 
get_address_space_device_hw_funcs(void)566 const struct AddressSpaceHwFuncs* get_address_space_device_hw_funcs(void) {
567     return sAddressSpaceHwFuncs;
568 }
569 
address_space_set_vm_operations(const QAndroidVmOperations * vmops)570 void address_space_set_vm_operations(const QAndroidVmOperations* vmops) {
571     sVmOps = vmops;
572 }
573 
574 } // extern "C"
575 
576 namespace android {
577 namespace emulation {
578 
goldfish_address_space_set_vm_operations(const QAndroidVmOperations * vmops)579 void goldfish_address_space_set_vm_operations(const QAndroidVmOperations* vmops) {
580     sVmOps = vmops;
581 }
582 
goldfish_address_space_get_vm_operations()583 const QAndroidVmOperations* goldfish_address_space_get_vm_operations() {
584     return sVmOps;
585 }
586 
goldfish_address_space_memory_state_set_load_resources(AddressSpaceDeviceLoadResources resources)587 int goldfish_address_space_memory_state_set_load_resources(
588     AddressSpaceDeviceLoadResources resources) {
589     sAddressSpaceDeviceState()->setLoadResources(std::move(resources));
590     return 0;
591 }
592 
goldfish_address_space_memory_state_load(android::base::Stream * stream)593 int goldfish_address_space_memory_state_load(android::base::Stream *stream) {
594     return sAddressSpaceDeviceState()->load(stream) ? 0 : 1;
595 }
596 
goldfish_address_space_memory_state_save(android::base::Stream * stream)597 int goldfish_address_space_memory_state_save(android::base::Stream *stream) {
598     sAddressSpaceDeviceState()->save(stream);
599     return 0;
600 }
601 
602 }  // namespace emulation
603 }  // namespace android
604