1 // Copyright 2020 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 #pragma once 16 17 #include <inttypes.h> 18 #include <stdbool.h> 19 20 // GOLDFISH SYNC DEVICE 21 // The Goldfish sync driver is designed to provide a interface 22 // between the underlying host's sync device and the kernel's 23 // sw_sync. 24 // The purpose of the device/driver is to enable lightweight 25 // creation and signaling of timelines and fences 26 // in order to synchronize the guest with host-side graphics events. 27 28 // Each time the interrupt trips, the driver 29 // may perform a sw_sync operation. 30 31 // The operations are: 32 33 // Ready signal - used to mark when irq should lower 34 #define CMD_SYNC_READY 0 35 36 // Create a new timeline. writes timeline handle 37 #define CMD_CREATE_SYNC_TIMELINE 1 38 39 // Create a fence object. reads timeline handle and time argument. 40 // Writes fence fd to the SYNC_REG_HANDLE register. 41 #define CMD_CREATE_SYNC_FENCE 2 42 43 // Increments timeline. reads timeline handle and time argument 44 #define CMD_SYNC_TIMELINE_INC 3 45 46 // Destroys a timeline. reads timeline handle 47 #define CMD_DESTROY_SYNC_TIMELINE 4 48 49 // Starts a wait on the host with 50 // the given glsync object and sync thread handle. 51 #define CMD_TRIGGER_HOST_WAIT 5 52 53 // The register layout is: 54 55 #define SYNC_REG_BATCH_COMMAND 0x00 // host->guest batch commands 56 #define SYNC_REG_BATCH_GUESTCOMMAND 0x04 // guest->host batch commands 57 #define SYNC_REG_BATCH_COMMAND_ADDR 0x08 // communicate physical address of host->guest batch commands 58 #define SYNC_REG_BATCH_COMMAND_ADDR_HIGH 0x0c // 64-bit part 59 #define SYNC_REG_BATCH_GUESTCOMMAND_ADDR 0x10 // communicate physical address of guest->host commands 60 #define SYNC_REG_BATCH_GUESTCOMMAND_ADDR_HIGH 0x14 // 64-bit part 61 #define SYNC_REG_INIT 0x18 // to signal that the device has been detected by the kernel 62 63 #define GUEST_TRIGGERED(cmd) (cmd == CMD_SYNC_READY || \ 64 cmd == CMD_TRIGGER_HOST_WAIT) 65 66 typedef void (*trigger_wait_fn_t)(uint64_t, uint64_t, uint64_t); 67 68 // The commands below operate on Android sync "timelines" and 69 // "fences". The basic concept is as follows. 70 // - Timeline and fences work together as a state to determine 71 // which events have completed. The timeline abstraction 72 // is used to represent a monotonic ordering of events, 73 // while fences represent levels of progress along 74 // timelines. By having different threads wait on fences 75 // until their associated timelines make the required progress, 76 // we can synchronize multiple threads within a process 77 // and with binder, across processes. 78 // - What follows is an abstract definition of that concept 79 // that does not match implementation exactly, but is 80 // sufficient for our purposes: 81 // - A timeline is a represnted by a single uint32_t, known as 82 // its "value". Over time, the value may increase. 83 // timeline : value 84 // - Let "timeline-id" be a uint64_t that uniquely identifies each 85 // timeline. 86 // A fence is an immutable map from timeline-id's to values: 87 // fence : map(timeline-id -> value). We will refer to the 88 // "timeline-id-values" of a fence to be the set of all pairs 89 // (timeline-id, value) that comprise the mapping. 90 // - Let "fence-id" be an int that uniquely identifies each fence. 91 // This is also known as a "fence fd". 92 // The important state is represented by a pair of maps: 93 // (T = map(timeline-id -> timeline), F = map(fence-id -> fence)). 94 // This state may change over time, with timelines and fences 95 // being added or removed. 96 // For any state, we care primarily about the "signaled" status 97 // of the fences within. 98 // - Each fence in the map from fence-id's to fences is 99 // signaled if: 100 // - For all timeline-id-values = (timeline-id, value) 101 // of that fence, T[timeline-id] >= value. 102 // Or, timeline-id does not exist in T's keys. 103 // - Otherwise, it is considered "unsignaled." 104 // The functions below operate with the above abstraction in mind. 105 // They all mutate a particular collection of fences and timelines. 106 // We can think of them as implicitly taking a state (T, F) 107 // as input and returning a new one (T', F') that is possibly updated, 108 // according to the changes described. The new collection then 109 // serves as the true abstract state for all further operations. 110 111 // |goldfish_sync_create_timeline| creates a new timeline 112 // with value 0. The timeline id is returned. 113 uint64_t goldfish_sync_create_timeline(); 114 115 // |goldfish_sync_create_fence| creates a fence 116 // that has a single timeline-id-value pair as its map. 117 // The first two arguments comprise the pair. 118 // Returns a unique identifier for the fence. 119 // Note that this implementation only allows the creation of 120 // fences associated with a single timeline-id-value pair. 121 int goldfish_sync_create_fence(uint64_t timeline, uint32_t pt); 122 123 // |goldfish_sync_timeline_inc| advances the value component 124 // of a given timeline by |howmuch|; that is, if 125 // (t, v) is the timeline-id and value of a timeline before this call, 126 // (t, v + |howmuch|) is the value after. 127 // Thus, this may end up changing some fence objects to signaled state. 128 void goldfish_sync_timeline_inc(uint64_t timeline, uint32_t howmuch); 129 130 // |goldfish_sync_destroy_timeline| removes the key |timeline| 131 // from the global timeline map. 132 // Any fence objects whose only timeline-id-value (t, v) is such that 133 // t == |timeline| would be considered signaled. 134 // If there are any other timeline-id-values, the fence may still be 135 // unsignaled. We would need the other timelines referenced by this fence 136 // to have reached the target value of this fence, fence[timeline]. 137 void goldfish_sync_destroy_timeline(uint64_t timeline); 138 139 // Registering callbacks for goldfish sync ops 140 // Currently, only trigger_wait is supported. 141 void goldfish_sync_register_trigger_wait(trigger_wait_fn_t trigger_fn); 142 143 // If the virtual device doesn't actually exist (e.g., when 144 // using QEMU1), query that using this function: 145 bool goldfish_sync_device_exists(); 146 147 // Function types for sending commands to the virtual device. 148 typedef void (*queue_device_command_t) 149 (uint32_t cmd, uint64_t handle, uint32_t time_arg, 150 uint64_t hostcmd_handle); 151 152 typedef struct GoldfishSyncDeviceInterface { 153 // Callback for all communications with virtual device 154 queue_device_command_t doHostCommand; 155 156 // Callbacks to register other callbacks for triggering 157 // OpenGL waits from the guest 158 void (*registerTriggerWait)(trigger_wait_fn_t); 159 } GoldfishSyncDeviceInterface; 160 161 // The virtual device will call |goldfish_sync_set_hw_funcs| 162 // to connect up to the AndroidEmu part. 163 extern void 164 goldfish_sync_set_hw_funcs(GoldfishSyncDeviceInterface* hw_funcs); 165 166 // The virtual device calls this |goldfish_sync_receive_hostcmd_result| 167 // when it receives a reply for host->guest commands that support 168 // that protocol. 169 extern void 170 goldfish_sync_receive_hostcmd_result(uint32_t cmd, 171 uint64_t handle, 172 uint32_t time_arg, 173 uint64_t hostcmd_handle); 174