1 /*
2 * Copyright 2023 Google
3 * SPDX-License-Identifier: MIT
4 */
5
6 #include "GoldfishAddressSpaceStream.h"
7
8 #include "goldfish_address_space.h"
9 #include "util/log.h"
10
createGoldfishAddressSpaceStream(size_t ignored_bufSize)11 AddressSpaceStream* createGoldfishAddressSpaceStream(size_t ignored_bufSize) {
12 // Ignore incoming ignored_bufSize
13 (void)ignored_bufSize;
14
15 auto handle = goldfish_address_space_open();
16 address_space_handle_t child_device_handle;
17
18 if (!goldfish_address_space_set_subdevice_type(handle, GoldfishAddressSpaceSubdeviceType::Graphics, &child_device_handle)) {
19 mesa_loge("AddressSpaceStream::create failed (initial device create)\n");
20 goldfish_address_space_close(handle);
21 return nullptr;
22 }
23
24 struct address_space_ping request;
25 request.metadata = ASG_GET_RING;
26 if (!goldfish_address_space_ping(child_device_handle, &request)) {
27 mesa_loge("AddressSpaceStream::create failed (get ring)\n");
28 goldfish_address_space_close(child_device_handle);
29 return nullptr;
30 }
31
32 uint64_t ringOffset = request.metadata;
33
34 request.metadata = ASG_GET_BUFFER;
35 if (!goldfish_address_space_ping(child_device_handle, &request)) {
36 mesa_loge("AddressSpaceStream::create failed (get buffer)\n");
37 goldfish_address_space_close(child_device_handle);
38 return nullptr;
39 }
40
41 uint64_t bufferOffset = request.metadata;
42 uint64_t bufferSize = request.size;
43
44 if (!goldfish_address_space_claim_shared(
45 child_device_handle, ringOffset, sizeof(asg_ring_storage))) {
46 mesa_loge("AddressSpaceStream::create failed (claim ring storage)\n");
47 goldfish_address_space_close(child_device_handle);
48 return nullptr;
49 }
50
51 if (!goldfish_address_space_claim_shared(
52 child_device_handle, bufferOffset, bufferSize)) {
53 mesa_loge("AddressSpaceStream::create failed (claim buffer storage)\n");
54 goldfish_address_space_unclaim_shared(child_device_handle, ringOffset);
55 goldfish_address_space_close(child_device_handle);
56 return nullptr;
57 }
58
59 char* ringPtr = (char*)goldfish_address_space_map(
60 child_device_handle, ringOffset, sizeof(struct asg_ring_storage));
61
62 if (!ringPtr) {
63 mesa_loge("AddressSpaceStream::create failed (map ring storage)\n");
64 goldfish_address_space_unclaim_shared(child_device_handle, bufferOffset);
65 goldfish_address_space_unclaim_shared(child_device_handle, ringOffset);
66 goldfish_address_space_close(child_device_handle);
67 return nullptr;
68 }
69
70 char* bufferPtr = (char*)goldfish_address_space_map(
71 child_device_handle, bufferOffset, bufferSize);
72
73 if (!bufferPtr) {
74 mesa_loge("AddressSpaceStream::create failed (map buffer storage)\n");
75 goldfish_address_space_unmap(ringPtr, sizeof(struct asg_ring_storage));
76 goldfish_address_space_unclaim_shared(child_device_handle, bufferOffset);
77 goldfish_address_space_unclaim_shared(child_device_handle, ringOffset);
78 goldfish_address_space_close(child_device_handle);
79 return nullptr;
80 }
81
82 struct asg_context context =
83 asg_context_create(
84 ringPtr, bufferPtr, bufferSize);
85
86 request.metadata = ASG_SET_VERSION;
87 request.size = 1; // version 1
88
89 if (!goldfish_address_space_ping(child_device_handle, &request)) {
90 mesa_loge("AddressSpaceStream::create failed (get buffer)\n");
91 goldfish_address_space_unmap(bufferPtr, bufferSize);
92 goldfish_address_space_unmap(ringPtr, sizeof(struct asg_ring_storage));
93 goldfish_address_space_unclaim_shared(child_device_handle, bufferOffset);
94 goldfish_address_space_unclaim_shared(child_device_handle, ringOffset);
95 goldfish_address_space_close(child_device_handle);
96 return nullptr;
97 }
98
99 uint32_t version = request.size;
100
101 context.ring_config->transfer_mode = 1;
102 context.ring_config->host_consumed_pos = 0;
103 context.ring_config->guest_write_pos = 0;
104
105 struct address_space_ops ops = {
106 .open = goldfish_address_space_open,
107 .close = goldfish_address_space_close,
108 .claim_shared = goldfish_address_space_claim_shared,
109 .unclaim_shared = goldfish_address_space_unclaim_shared,
110 .map = goldfish_address_space_map,
111 .unmap = goldfish_address_space_unmap,
112 .set_subdevice_type = goldfish_address_space_set_subdevice_type,
113 .ping = goldfish_address_space_ping,
114 };
115
116 AddressSpaceStream* res = new AddressSpaceStream(child_device_handle, version, context,
117 ringOffset, bufferOffset, ops);
118
119 return res;
120 }
121