1 /* 2 * Multifd common functions 3 * 4 * Copyright (c) 2019-2020 Red Hat Inc 5 * 6 * Authors: 7 * Juan Quintela <quintela@redhat.com> 8 * 9 * This work is licensed under the terms of the GNU GPL, version 2 or later. 10 * See the COPYING file in the top-level directory. 11 */ 12 13 #ifndef QEMU_MIGRATION_MULTIFD_H 14 #define QEMU_MIGRATION_MULTIFD_H 15 16 #include "exec/target_page.h" 17 #include "ram.h" 18 19 typedef struct MultiFDRecvData MultiFDRecvData; 20 typedef struct MultiFDSendData MultiFDSendData; 21 22 bool multifd_send_setup(void); 23 void multifd_send_shutdown(void); 24 void multifd_send_channel_created(void); 25 int multifd_recv_setup(Error **errp); 26 void multifd_recv_cleanup(void); 27 void multifd_recv_shutdown(void); 28 bool multifd_recv_all_channels_created(void); 29 void multifd_recv_new_channel(QIOChannel *ioc, Error **errp); 30 void multifd_recv_sync_main(void); 31 int multifd_send_sync_main(void); 32 bool multifd_queue_page(RAMBlock *block, ram_addr_t offset); 33 bool multifd_recv(void); 34 MultiFDRecvData *multifd_get_recv_data(void); 35 36 /* Multifd Compression flags */ 37 #define MULTIFD_FLAG_SYNC (1 << 0) 38 39 /* We reserve 4 bits for compression methods */ 40 #define MULTIFD_FLAG_COMPRESSION_MASK (0xf << 1) 41 /* we need to be compatible. Before compression value was 0 */ 42 #define MULTIFD_FLAG_NOCOMP (0 << 1) 43 #define MULTIFD_FLAG_ZLIB (1 << 1) 44 #define MULTIFD_FLAG_ZSTD (2 << 1) 45 #define MULTIFD_FLAG_QPL (4 << 1) 46 #define MULTIFD_FLAG_UADK (8 << 1) 47 48 /* This value needs to be a multiple of qemu_target_page_size() */ 49 #define MULTIFD_PACKET_SIZE (512 * 1024) 50 51 typedef struct { 52 uint32_t magic; 53 uint32_t version; 54 uint32_t flags; 55 /* maximum number of allocated pages */ 56 uint32_t pages_alloc; 57 /* non zero pages */ 58 uint32_t normal_pages; 59 /* size of the next packet that contains pages */ 60 uint32_t next_packet_size; 61 uint64_t packet_num; 62 /* zero pages */ 63 uint32_t zero_pages; 64 uint32_t unused32[1]; /* Reserved for future use */ 65 uint64_t unused64[3]; /* Reserved for future use */ 66 char ramblock[256]; 67 /* 68 * This array contains the pointers to: 69 * - normal pages (initial normal_pages entries) 70 * - zero pages (following zero_pages entries) 71 */ 72 uint64_t offset[]; 73 } __attribute__((packed)) MultiFDPacket_t; 74 75 typedef struct { 76 /* number of used pages */ 77 uint32_t num; 78 /* number of normal pages */ 79 uint32_t normal_num; 80 RAMBlock *block; 81 /* offset of each page */ 82 ram_addr_t offset[]; 83 } MultiFDPages_t; 84 85 struct MultiFDRecvData { 86 void *opaque; 87 size_t size; 88 /* for preadv */ 89 off_t file_offset; 90 }; 91 92 typedef enum { 93 MULTIFD_PAYLOAD_NONE, 94 MULTIFD_PAYLOAD_RAM, 95 } MultiFDPayloadType; 96 97 typedef union MultiFDPayload { 98 MultiFDPages_t ram; 99 } MultiFDPayload; 100 101 struct MultiFDSendData { 102 MultiFDPayloadType type; 103 MultiFDPayload u; 104 }; 105 106 static inline bool multifd_payload_empty(MultiFDSendData *data) 107 { 108 return data->type == MULTIFD_PAYLOAD_NONE; 109 } 110 111 static inline void multifd_set_payload_type(MultiFDSendData *data, 112 MultiFDPayloadType type) 113 { 114 data->type = type; 115 } 116 117 typedef struct { 118 /* Fields are only written at creating/deletion time */ 119 /* No lock required for them, they are read only */ 120 121 /* channel number */ 122 uint8_t id; 123 /* channel thread name */ 124 char *name; 125 /* channel thread id */ 126 QemuThread thread; 127 bool thread_created; 128 QemuThread tls_thread; 129 bool tls_thread_created; 130 /* communication channel */ 131 QIOChannel *c; 132 /* packet allocated len */ 133 uint32_t packet_len; 134 /* multifd flags for sending ram */ 135 int write_flags; 136 137 /* sem where to wait for more work */ 138 QemuSemaphore sem; 139 /* syncs main thread and channels */ 140 QemuSemaphore sem_sync; 141 142 /* multifd flags for each packet */ 143 uint32_t flags; 144 /* 145 * The sender thread has work to do if either of below boolean is set. 146 * 147 * @pending_job: a job is pending 148 * @pending_sync: a sync request is pending 149 * 150 * For both of these fields, they're only set by the requesters, and 151 * cleared by the multifd sender threads. 152 */ 153 bool pending_job; 154 bool pending_sync; 155 MultiFDSendData *data; 156 157 /* thread local variables. No locking required */ 158 159 /* pointer to the packet */ 160 MultiFDPacket_t *packet; 161 /* size of the next packet that contains pages */ 162 uint32_t next_packet_size; 163 /* packets sent through this channel */ 164 uint64_t packets_sent; 165 /* buffers to send */ 166 struct iovec *iov; 167 /* number of iovs used */ 168 uint32_t iovs_num; 169 /* used for compression methods */ 170 void *compress_data; 171 } MultiFDSendParams; 172 173 typedef struct { 174 /* Fields are only written at creating/deletion time */ 175 /* No lock required for them, they are read only */ 176 177 /* channel number */ 178 uint8_t id; 179 /* channel thread name */ 180 char *name; 181 /* channel thread id */ 182 QemuThread thread; 183 bool thread_created; 184 /* communication channel */ 185 QIOChannel *c; 186 /* packet allocated len */ 187 uint32_t packet_len; 188 189 /* syncs main thread and channels */ 190 QemuSemaphore sem_sync; 191 /* sem where to wait for more work */ 192 QemuSemaphore sem; 193 194 /* this mutex protects the following parameters */ 195 QemuMutex mutex; 196 /* should this thread finish */ 197 bool quit; 198 /* multifd flags for each packet */ 199 uint32_t flags; 200 /* global number of generated multifd packets */ 201 uint64_t packet_num; 202 int pending_job; 203 MultiFDRecvData *data; 204 205 /* thread local variables. No locking required */ 206 207 /* pointer to the packet */ 208 MultiFDPacket_t *packet; 209 /* size of the next packet that contains pages */ 210 uint32_t next_packet_size; 211 /* packets received through this channel */ 212 uint64_t packets_recved; 213 /* ramblock */ 214 RAMBlock *block; 215 /* ramblock host address */ 216 uint8_t *host; 217 /* buffers to recv */ 218 struct iovec *iov; 219 /* Pages that are not zero */ 220 ram_addr_t *normal; 221 /* num of non zero pages */ 222 uint32_t normal_num; 223 /* Pages that are zero */ 224 ram_addr_t *zero; 225 /* num of zero pages */ 226 uint32_t zero_num; 227 /* used for de-compression methods */ 228 void *compress_data; 229 } MultiFDRecvParams; 230 231 typedef struct { 232 /* 233 * The send_setup, send_cleanup, send_prepare are only called on 234 * the QEMU instance at the migration source. 235 */ 236 237 /* 238 * Setup for sending side. Called once per channel during channel 239 * setup phase. 240 * 241 * Must allocate p->iov. If packets are in use (default), one 242 * extra iovec must be allocated for the packet header. Any memory 243 * allocated in this hook must be released at send_cleanup. 244 * 245 * p->write_flags may be used for passing flags to the QIOChannel. 246 * 247 * p->compression_data may be used by compression methods to store 248 * compression data. 249 */ 250 int (*send_setup)(MultiFDSendParams *p, Error **errp); 251 252 /* 253 * Cleanup for sending side. Called once per channel during 254 * channel cleanup phase. 255 */ 256 void (*send_cleanup)(MultiFDSendParams *p, Error **errp); 257 258 /* 259 * Prepare the send packet. Called as a result of multifd_send() 260 * on the client side, with p pointing to the MultiFDSendParams of 261 * a channel that is currently idle. 262 * 263 * Must populate p->iov with the data to be sent, increment 264 * p->iovs_num to match the amount of iovecs used and set 265 * p->next_packet_size with the amount of data currently present 266 * in p->iov. 267 * 268 * Must indicate whether this is a compression packet by setting 269 * p->flags. 270 * 271 * As a last step, if packets are in use (default), must prepare 272 * the packet by calling multifd_send_fill_packet(). 273 */ 274 int (*send_prepare)(MultiFDSendParams *p, Error **errp); 275 276 /* 277 * The recv_setup, recv_cleanup, recv are only called on the QEMU 278 * instance at the migration destination. 279 */ 280 281 /* 282 * Setup for receiving side. Called once per channel during 283 * channel setup phase. May be empty. 284 * 285 * May allocate data structures for the receiving of data. May use 286 * p->iov. Compression methods may use p->compress_data. 287 */ 288 int (*recv_setup)(MultiFDRecvParams *p, Error **errp); 289 290 /* 291 * Cleanup for receiving side. Called once per channel during 292 * channel cleanup phase. May be empty. 293 */ 294 void (*recv_cleanup)(MultiFDRecvParams *p); 295 296 /* 297 * Data receive method. Called as a result of multifd_recv() on 298 * the client side, with p pointing to the MultiFDRecvParams of a 299 * channel that is currently idle. Only called if there is data 300 * available to receive. 301 * 302 * Must validate p->flags according to what was set at 303 * send_prepare. 304 * 305 * Must read the data from the QIOChannel p->c. 306 */ 307 int (*recv)(MultiFDRecvParams *p, Error **errp); 308 } MultiFDMethods; 309 310 void multifd_register_ops(int method, const MultiFDMethods *ops); 311 void multifd_send_fill_packet(MultiFDSendParams *p); 312 bool multifd_send_prepare_common(MultiFDSendParams *p); 313 void multifd_send_zero_page_detect(MultiFDSendParams *p); 314 void multifd_recv_zero_page_process(MultiFDRecvParams *p); 315 316 static inline void multifd_send_prepare_header(MultiFDSendParams *p) 317 { 318 p->iov[0].iov_len = p->packet_len; 319 p->iov[0].iov_base = p->packet; 320 p->iovs_num++; 321 } 322 323 void multifd_channel_connect(MultiFDSendParams *p, QIOChannel *ioc); 324 bool multifd_send(MultiFDSendData **send_data); 325 MultiFDSendData *multifd_send_data_alloc(void); 326 327 static inline uint32_t multifd_ram_page_size(void) 328 { 329 return qemu_target_page_size(); 330 } 331 332 static inline uint32_t multifd_ram_page_count(void) 333 { 334 return MULTIFD_PACKET_SIZE / qemu_target_page_size(); 335 } 336 337 void multifd_ram_save_setup(void); 338 void multifd_ram_save_cleanup(void); 339 int multifd_ram_flush_and_sync(void); 340 size_t multifd_ram_payload_size(void); 341 void multifd_ram_fill_packet(MultiFDSendParams *p); 342 int multifd_ram_unfill_packet(MultiFDRecvParams *p, Error **errp); 343 #endif 344