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 "host-common/DeviceContextRunner.h"
18 #include "host-common/goldfish_sync.h"
19 #include "host-common/VmLock.h"
20 #include "aemu/base/files/Stream.h"
21 
22 #include <vector>
23 
24 #define DEBUG 0
25 
26 #if DEBUG
27 #define DPRINT(...) do { \
28     if (!VERBOSE_CHECK(goldfishsync)) VERBOSE_ENABLE(goldfishsync); \
29     VERBOSE_TID_FUNCTION_DPRINT(goldfishsync, __VA_ARGS__); } while(0)
30 #else
31 #define DPRINT(...)
32 #endif
33 
34 #define ERR(...) do { \
35     derror(__VA_ARGS__); \
36 } while(0)
37 
38 namespace android {
39 
40 ////////////////////////////////////////////////////////////////////////////////
41 // GoldfishSyncCommandQueue ensures that commands sent to the Goldfish Sync
42 // virtual device take place in "device context"; that is, the commands
43 // are only executed while the main loop has the VM lock. Like PipeWaker
44 // of AndroidPipe, this class derives from DeviceContextRunner for this
45 // functionality.
46 // This class is only used for host->guest commands for goldfish sync device,
47 // and mainly timeline increment at that. The way to use
48 // GoldfishSyncCommandQueue in general is to call |hostSignal| with the
49 // particular details of the host->guest command being issued.
50 //
51 // However, make sure that |setQueueCommand| has been called on
52 // goldifish sync device initialization, which properly hooks up the
53 // GoldfishSyncCommandQueue with the particular virtual device function
54 // that actually raises IRQ's, and that |initThreading| has been called
55 // in a main loop context, preferably in qemu-setup.cpp.
56 
57 struct GoldfishSyncWakeInfo {
58     uint64_t handle;
59     uint64_t hostcmd_handle;
60     uint32_t cmd;
61     uint32_t time_arg;
62 };
63 
64 class GoldfishSyncCommandQueue final :
65     public DeviceContextRunner<GoldfishSyncWakeInfo> {
66 
67 public:
68     // Like with the PipeWaker for AndroidPipe,
69     // we need to process all commands
70     // in a context where we hold the VM lock.
71     static void initThreading(VmLock* vmLock);
72 
73     // Goldfish sync virtual device will give out its own
74     // callback for queueing commands to it.
75     static void setQueueCommand(queue_device_command_t fx);
76 
77     // Main interface for all Goldfish sync device
78     // communications.
79     static void hostSignal(uint32_t cmd,
80                            uint64_t handle,
81                            uint32_t time_arg,
82                            uint64_t hostcmd_handle);
83 
84     // Save/load pending operations.
85     static void save(android::base::Stream* stream);
86     static void load(android::base::Stream* stream);
87 
88 private:
89 
90     virtual void performDeviceOperation(const GoldfishSyncWakeInfo& cmd) override;
91 
92     queue_device_command_t tellSyncDevice = nullptr;
93 };
94 
95 } // namespace android
96