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