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