]>
Commit | Line | Data |
---|---|---|
0d71f708 JD |
1 | /* |
2 | * QEMU Hyper-V VMBus | |
3 | * | |
4 | * Copyright (c) 2017-2018 Virtuozzo International GmbH. | |
5 | * | |
6 | * This work is licensed under the terms of the GNU GPL, version 2 or later. | |
7 | * See the COPYING file in the top-level directory. | |
8 | */ | |
9 | ||
10 | #ifndef HW_HYPERV_VMBUS_H | |
11 | #define HW_HYPERV_VMBUS_H | |
12 | ||
13 | #include "sysemu/sysemu.h" | |
14 | #include "sysemu/dma.h" | |
15 | #include "hw/qdev-core.h" | |
16 | #include "migration/vmstate.h" | |
17 | #include "hw/hyperv/vmbus-proto.h" | |
18 | #include "qemu/uuid.h" | |
db1015e9 | 19 | #include "qom/object.h" |
0d71f708 JD |
20 | |
21 | #define TYPE_VMBUS_DEVICE "vmbus-dev" | |
22 | ||
db1015e9 EH |
23 | typedef struct VMBusDevice VMBusDevice; |
24 | typedef struct VMBusDeviceClass VMBusDeviceClass; | |
0d71f708 JD |
25 | #define VMBUS_DEVICE(obj) \ |
26 | OBJECT_CHECK(VMBusDevice, (obj), TYPE_VMBUS_DEVICE) | |
27 | #define VMBUS_DEVICE_CLASS(klass) \ | |
28 | OBJECT_CLASS_CHECK(VMBusDeviceClass, (klass), TYPE_VMBUS_DEVICE) | |
29 | #define VMBUS_DEVICE_GET_CLASS(obj) \ | |
30 | OBJECT_GET_CLASS(VMBusDeviceClass, (obj), TYPE_VMBUS_DEVICE) | |
31 | ||
240b6cd7 EH |
32 | #define TYPE_VMBUS "vmbus" |
33 | typedef struct VMBus VMBus; | |
34 | #define VMBUS(obj) OBJECT_CHECK(VMBus, (obj), TYPE_VMBUS) | |
35 | ||
0d71f708 JD |
36 | /* |
37 | * Object wrapping a GPADL -- GPA Descriptor List -- an array of guest physical | |
38 | * pages, to be used for various buffers shared between the host and the guest. | |
39 | */ | |
40 | typedef struct VMBusGpadl VMBusGpadl; | |
41 | /* | |
42 | * VMBus channel -- a pair of ring buffers for either direction, placed within | |
43 | * one GPADL, and the associated notification means. | |
44 | */ | |
45 | typedef struct VMBusChannel VMBusChannel; | |
46 | /* | |
47 | * Base class for VMBus devices. Includes one or more channels. Identified by | |
48 | * class GUID and instance GUID. | |
49 | */ | |
0d71f708 JD |
50 | |
51 | typedef void(*VMBusChannelNotifyCb)(struct VMBusChannel *chan); | |
52 | ||
db1015e9 | 53 | struct VMBusDeviceClass { |
0d71f708 JD |
54 | DeviceClass parent; |
55 | ||
56 | QemuUUID classid; | |
57 | QemuUUID instanceid; /* Fixed UUID for singleton devices */ | |
58 | uint16_t channel_flags; | |
59 | uint16_t mmio_size_mb; | |
60 | ||
61 | /* Extentions to standard device callbacks */ | |
62 | void (*vmdev_realize)(VMBusDevice *vdev, Error **errp); | |
63 | void (*vmdev_unrealize)(VMBusDevice *vdev); | |
64 | void (*vmdev_reset)(VMBusDevice *vdev); | |
65 | /* | |
66 | * Calculate the number of channels based on the device properties. Called | |
67 | * at realize time. | |
68 | **/ | |
69 | uint16_t (*num_channels)(VMBusDevice *vdev); | |
70 | /* | |
71 | * Device-specific actions to complete the otherwise successful process of | |
72 | * opening a channel. | |
73 | * Return 0 on success, -errno on failure. | |
74 | */ | |
75 | int (*open_channel)(VMBusChannel *chan); | |
76 | /* | |
77 | * Device-specific actions to perform before closing a channel. | |
78 | */ | |
79 | void (*close_channel)(VMBusChannel *chan); | |
80 | /* | |
81 | * Main device worker; invoked in response to notifications from either | |
82 | * side, when there's work to do with the data in the channel ring buffers. | |
83 | */ | |
84 | VMBusChannelNotifyCb chan_notify_cb; | |
db1015e9 | 85 | }; |
0d71f708 JD |
86 | |
87 | struct VMBusDevice { | |
88 | DeviceState parent; | |
89 | QemuUUID instanceid; | |
90 | uint16_t num_channels; | |
91 | VMBusChannel *channels; | |
92 | AddressSpace *dma_as; | |
93 | }; | |
94 | ||
95 | extern const VMStateDescription vmstate_vmbus_dev; | |
96 | ||
97 | /* | |
98 | * A unit of work parsed out of a message in the receive (i.e. guest->host) | |
99 | * ring buffer of a channel. It's supposed to be subclassed (through | |
100 | * embedding) by the specific devices. | |
101 | */ | |
102 | typedef struct VMBusChanReq { | |
103 | VMBusChannel *chan; | |
104 | uint16_t pkt_type; | |
105 | uint32_t msglen; | |
106 | void *msg; | |
107 | uint64_t transaction_id; | |
108 | bool need_comp; | |
109 | QEMUSGList sgl; | |
110 | } VMBusChanReq; | |
111 | ||
112 | VMBusDevice *vmbus_channel_device(VMBusChannel *chan); | |
113 | VMBusChannel *vmbus_device_channel(VMBusDevice *dev, uint32_t chan_idx); | |
114 | uint32_t vmbus_channel_idx(VMBusChannel *chan); | |
115 | bool vmbus_channel_is_open(VMBusChannel *chan); | |
116 | ||
117 | /* | |
118 | * Notify (on guest's behalf) the host side of the channel that there's data in | |
119 | * the ringbuffer to process. | |
120 | */ | |
121 | void vmbus_channel_notify_host(VMBusChannel *chan); | |
122 | ||
123 | /* | |
124 | * Reserve space for a packet in the send (i.e. host->guest) ringbuffer. If | |
125 | * there isn't enough room, indicate that to the guest, to be notified when it | |
126 | * becomes available. | |
127 | * Return 0 on success, negative errno on failure. | |
128 | * The ringbuffer indices are NOT updated, the requested space indicator may. | |
129 | */ | |
130 | int vmbus_channel_reserve(VMBusChannel *chan, | |
131 | uint32_t desclen, uint32_t msglen); | |
132 | ||
133 | /* | |
134 | * Send a packet to the guest. The space for the packet MUST be reserved | |
135 | * first. | |
136 | * Return total number of bytes placed in the send ringbuffer on success, | |
137 | * negative errno on failure. | |
138 | * The ringbuffer indices are updated on success, and the guest is signaled if | |
139 | * needed. | |
140 | */ | |
141 | ssize_t vmbus_channel_send(VMBusChannel *chan, uint16_t pkt_type, | |
142 | void *desc, uint32_t desclen, | |
143 | void *msg, uint32_t msglen, | |
144 | bool need_comp, uint64_t transaction_id); | |
145 | ||
146 | /* | |
147 | * Prepare to fetch a batch of packets from the receive ring buffer. | |
148 | * Return 0 on success, negative errno on failure. | |
149 | */ | |
150 | int vmbus_channel_recv_start(VMBusChannel *chan); | |
151 | ||
152 | /* | |
153 | * Shortcut for a common case of sending a simple completion packet with no | |
154 | * auxiliary descriptors. | |
155 | */ | |
156 | ssize_t vmbus_channel_send_completion(VMBusChanReq *req, | |
157 | void *msg, uint32_t msglen); | |
158 | ||
159 | /* | |
160 | * Peek at the receive (i.e. guest->host) ring buffer and extract a unit of | |
161 | * work (a device-specific subclass of VMBusChanReq) from a packet if there's | |
162 | * one. | |
163 | * Return an allocated buffer, containing the request of @size with filled | |
164 | * VMBusChanReq at the beginning, followed by the message payload, or NULL on | |
165 | * failure. | |
166 | * The ringbuffer indices are NOT updated, nor is the private copy of the read | |
167 | * index. | |
168 | */ | |
169 | void *vmbus_channel_recv_peek(VMBusChannel *chan, uint32_t size); | |
170 | ||
171 | /* | |
172 | * Update the private copy of the read index once the preceding peek is deemed | |
173 | * successful. | |
174 | * The ringbuffer indices are NOT updated. | |
175 | */ | |
176 | void vmbus_channel_recv_pop(VMBusChannel *chan); | |
177 | ||
178 | /* | |
179 | * Propagate the private copy of the read index into the receive ring buffer, | |
180 | * and thus complete the reception of a series of packets. Notify guest if | |
181 | * needed. | |
182 | * Return the number of bytes popped off the receive ring buffer by the | |
183 | * preceding recv_peek/recv_pop calls on success, negative errno on failure. | |
184 | */ | |
185 | ssize_t vmbus_channel_recv_done(VMBusChannel *chan); | |
186 | ||
187 | /* | |
188 | * Free the request allocated by vmbus_channel_recv_peek, together with its | |
189 | * fields. | |
190 | */ | |
191 | void vmbus_free_req(void *req); | |
192 | ||
193 | /* | |
194 | * Find and reference a GPADL by @gpadl_id. | |
195 | * If not found return NULL. | |
196 | */ | |
197 | VMBusGpadl *vmbus_get_gpadl(VMBusChannel *chan, uint32_t gpadl_id); | |
198 | ||
199 | /* | |
200 | * Unreference @gpadl. If the reference count drops to zero, free it. | |
201 | * @gpadl may be NULL, in which case nothing is done. | |
202 | */ | |
203 | void vmbus_put_gpadl(VMBusGpadl *gpadl); | |
204 | ||
205 | /* | |
206 | * Calculate total length in bytes of @gpadl. | |
207 | * @gpadl must be valid. | |
208 | */ | |
209 | uint32_t vmbus_gpadl_len(VMBusGpadl *gpadl); | |
210 | ||
211 | /* | |
212 | * Copy data from @iov to @gpadl at offset @off. | |
213 | * Return the number of bytes copied, or a negative status on failure. | |
214 | */ | |
215 | ssize_t vmbus_iov_to_gpadl(VMBusChannel *chan, VMBusGpadl *gpadl, uint32_t off, | |
216 | const struct iovec *iov, size_t iov_cnt); | |
217 | ||
218 | /* | |
219 | * Map SGList contained in the request @req, at offset @off and no more than | |
220 | * @len bytes, for io in direction @dir, and populate @iov with the mapped | |
221 | * iovecs. | |
222 | * Return the number of iovecs mapped, or negative status on failure. | |
223 | */ | |
224 | int vmbus_map_sgl(VMBusChanReq *req, DMADirection dir, struct iovec *iov, | |
225 | unsigned iov_cnt, size_t len, size_t off); | |
226 | ||
227 | /* | |
228 | * Unmap *iov mapped with vmbus_map_sgl, marking the number of bytes @accessed. | |
229 | */ | |
230 | void vmbus_unmap_sgl(VMBusChanReq *req, DMADirection dir, struct iovec *iov, | |
231 | unsigned iov_cnt, size_t accessed); | |
232 | ||
4dd8a706 JD |
233 | void vmbus_save_req(QEMUFile *f, VMBusChanReq *req); |
234 | void *vmbus_load_req(QEMUFile *f, VMBusDevice *dev, uint32_t size); | |
235 | ||
0d71f708 | 236 | #endif |