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