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 "ram.h" 17 18 typedef struct MultiFDRecvData MultiFDRecvData; 19 20 bool multifd_send_setup(void); 21 void multifd_send_shutdown(void); 22 void multifd_send_channel_created(void); 23 int multifd_recv_setup(Error **errp); 24 void multifd_recv_cleanup(void); 25 void multifd_recv_shutdown(void); 26 bool multifd_recv_all_channels_created(void); 27 void multifd_recv_new_channel(QIOChannel *ioc, Error **errp); 28 void multifd_recv_sync_main(void); 29 int multifd_send_sync_main(void); 30 bool multifd_queue_page(RAMBlock *block, ram_addr_t offset); 31 bool multifd_recv(void); 32 MultiFDRecvData *multifd_get_recv_data(void); 33 34 /* Multifd Compression flags */ 35 #define MULTIFD_FLAG_SYNC (1 << 0) 36 37 /* We reserve 4 bits for compression methods */ 38 #define MULTIFD_FLAG_COMPRESSION_MASK (0xf << 1) 39 /* we need to be compatible. Before compression value was 0 */ 40 #define MULTIFD_FLAG_NOCOMP (0 << 1) 41 #define MULTIFD_FLAG_ZLIB (1 << 1) 42 #define MULTIFD_FLAG_ZSTD (2 << 1) 43 #define MULTIFD_FLAG_QPL (4 << 1) 44 #define MULTIFD_FLAG_UADK (8 << 1) 45 46 /* This value needs to be a multiple of qemu_target_page_size() */ 47 #define MULTIFD_PACKET_SIZE (512 * 1024) 48 49 typedef struct { 50 uint32_t magic; 51 uint32_t version; 52 uint32_t flags; 53 /* maximum number of allocated pages */ 54 uint32_t pages_alloc; 55 /* non zero pages */ 56 uint32_t normal_pages; 57 /* size of the next packet that contains pages */ 58 uint32_t next_packet_size; 59 uint64_t packet_num; 60 /* zero pages */ 61 uint32_t zero_pages; 62 uint32_t unused32[1]; /* Reserved for future use */ 63 uint64_t unused64[3]; /* Reserved for future use */ 64 char ramblock[256]; 65 /* 66 * This array contains the pointers to: 67 * - normal pages (initial normal_pages entries) 68 * - zero pages (following zero_pages entries) 69 */ 70 uint64_t offset[]; 71 } __attribute__((packed)) MultiFDPacket_t; 72 73 typedef struct { 74 /* number of used pages */ 75 uint32_t num; 76 /* number of normal pages */ 77 uint32_t normal_num; 78 /* number of allocated pages */ 79 uint32_t allocated; 80 /* offset of each page */ 81 ram_addr_t *offset; 82 RAMBlock *block; 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 struct { 93 /* Fields are only written at creating/deletion time */ 94 /* No lock required for them, they are read only */ 95 96 /* channel number */ 97 uint8_t id; 98 /* channel thread name */ 99 char *name; 100 /* channel thread id */ 101 QemuThread thread; 102 bool thread_created; 103 QemuThread tls_thread; 104 bool tls_thread_created; 105 /* communication channel */ 106 QIOChannel *c; 107 /* packet allocated len */ 108 uint32_t packet_len; 109 /* guest page size */ 110 uint32_t page_size; 111 /* number of pages in a full packet */ 112 uint32_t page_count; 113 /* multifd flags for sending ram */ 114 int write_flags; 115 116 /* sem where to wait for more work */ 117 QemuSemaphore sem; 118 /* syncs main thread and channels */ 119 QemuSemaphore sem_sync; 120 121 /* multifd flags for each packet */ 122 uint32_t flags; 123 /* 124 * The sender thread has work to do if either of below boolean is set. 125 * 126 * @pending_job: a job is pending 127 * @pending_sync: a sync request is pending 128 * 129 * For both of these fields, they're only set by the requesters, and 130 * cleared by the multifd sender threads. 131 */ 132 bool pending_job; 133 bool pending_sync; 134 /* array of pages to sent. 135 * The owner of 'pages' depends of 'pending_job' value: 136 * pending_job == 0 -> migration_thread can use it. 137 * pending_job != 0 -> multifd_channel can use it. 138 */ 139 MultiFDPages_t *pages; 140 141 /* thread local variables. No locking required */ 142 143 /* pointer to the packet */ 144 MultiFDPacket_t *packet; 145 /* size of the next packet that contains pages */ 146 uint32_t next_packet_size; 147 /* packets sent through this channel */ 148 uint64_t packets_sent; 149 /* non zero pages sent through this channel */ 150 uint64_t total_normal_pages; 151 /* zero pages sent through this channel */ 152 uint64_t total_zero_pages; 153 /* buffers to send */ 154 struct iovec *iov; 155 /* number of iovs used */ 156 uint32_t iovs_num; 157 /* used for compression methods */ 158 void *compress_data; 159 } MultiFDSendParams; 160 161 typedef struct { 162 /* Fields are only written at creating/deletion time */ 163 /* No lock required for them, they are read only */ 164 165 /* channel number */ 166 uint8_t id; 167 /* channel thread name */ 168 char *name; 169 /* channel thread id */ 170 QemuThread thread; 171 bool thread_created; 172 /* communication channel */ 173 QIOChannel *c; 174 /* packet allocated len */ 175 uint32_t packet_len; 176 /* guest page size */ 177 uint32_t page_size; 178 /* number of pages in a full packet */ 179 uint32_t page_count; 180 181 /* syncs main thread and channels */ 182 QemuSemaphore sem_sync; 183 /* sem where to wait for more work */ 184 QemuSemaphore sem; 185 186 /* this mutex protects the following parameters */ 187 QemuMutex mutex; 188 /* should this thread finish */ 189 bool quit; 190 /* multifd flags for each packet */ 191 uint32_t flags; 192 /* global number of generated multifd packets */ 193 uint64_t packet_num; 194 int pending_job; 195 MultiFDRecvData *data; 196 197 /* thread local variables. No locking required */ 198 199 /* pointer to the packet */ 200 MultiFDPacket_t *packet; 201 /* size of the next packet that contains pages */ 202 uint32_t next_packet_size; 203 /* packets received through this channel */ 204 uint64_t packets_recved; 205 /* ramblock */ 206 RAMBlock *block; 207 /* ramblock host address */ 208 uint8_t *host; 209 /* non zero pages recv through this channel */ 210 uint64_t total_normal_pages; 211 /* zero pages recv through this channel */ 212 uint64_t total_zero_pages; 213 /* buffers to recv */ 214 struct iovec *iov; 215 /* Pages that are not zero */ 216 ram_addr_t *normal; 217 /* num of non zero pages */ 218 uint32_t normal_num; 219 /* Pages that are zero */ 220 ram_addr_t *zero; 221 /* num of zero pages */ 222 uint32_t zero_num; 223 /* used for de-compression methods */ 224 void *compress_data; 225 } MultiFDRecvParams; 226 227 typedef struct { 228 /* Setup for sending side */ 229 int (*send_setup)(MultiFDSendParams *p, Error **errp); 230 /* Cleanup for sending side */ 231 void (*send_cleanup)(MultiFDSendParams *p, Error **errp); 232 /* Prepare the send packet */ 233 int (*send_prepare)(MultiFDSendParams *p, Error **errp); 234 /* Setup for receiving side */ 235 int (*recv_setup)(MultiFDRecvParams *p, Error **errp); 236 /* Cleanup for receiving side */ 237 void (*recv_cleanup)(MultiFDRecvParams *p); 238 /* Read all data */ 239 int (*recv)(MultiFDRecvParams *p, Error **errp); 240 } MultiFDMethods; 241 242 void multifd_register_ops(int method, MultiFDMethods *ops); 243 void multifd_send_fill_packet(MultiFDSendParams *p); 244 bool multifd_send_prepare_common(MultiFDSendParams *p); 245 void multifd_send_zero_page_detect(MultiFDSendParams *p); 246 void multifd_recv_zero_page_process(MultiFDRecvParams *p); 247 248 static inline void multifd_send_prepare_header(MultiFDSendParams *p) 249 { 250 p->iov[0].iov_len = p->packet_len; 251 p->iov[0].iov_base = p->packet; 252 p->iovs_num++; 253 } 254 255 void multifd_channel_connect(MultiFDSendParams *p, QIOChannel *ioc); 256 257 #endif 258