Juan Quintela | d32ca5a | 2020-01-22 16:16:07 +0100 | [diff] [blame] | 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 | int multifd_save_setup(Error **errp); |
| 17 | void multifd_save_cleanup(void); |
| 18 | int multifd_load_setup(Error **errp); |
Leonardo Bras | e5bac1f | 2023-02-10 03:36:28 -0300 | [diff] [blame] | 19 | void multifd_load_cleanup(void); |
Leonardo Bras | cfc3bcf | 2023-02-10 03:36:31 -0300 | [diff] [blame] | 20 | void multifd_load_shutdown(void); |
Juan Quintela | d32ca5a | 2020-01-22 16:16:07 +0100 | [diff] [blame] | 21 | bool multifd_recv_all_channels_created(void); |
manish.mishra | 6720c2b | 2022-12-20 18:44:18 +0000 | [diff] [blame] | 22 | void multifd_recv_new_channel(QIOChannel *ioc, Error **errp); |
Juan Quintela | d32ca5a | 2020-01-22 16:16:07 +0100 | [diff] [blame] | 23 | void multifd_recv_sync_main(void); |
Leonardo Bras | 33d7097 | 2022-05-13 03:28:35 -0300 | [diff] [blame] | 24 | int multifd_send_sync_main(QEMUFile *f); |
Juan Quintela | d32ca5a | 2020-01-22 16:16:07 +0100 | [diff] [blame] | 25 | int multifd_queue_page(QEMUFile *f, RAMBlock *block, ram_addr_t offset); |
| 26 | |
Juan Quintela | 7ec2c2b | 2019-01-04 15:30:06 +0100 | [diff] [blame] | 27 | /* Multifd Compression flags */ |
Juan Quintela | d32ca5a | 2020-01-22 16:16:07 +0100 | [diff] [blame] | 28 | #define MULTIFD_FLAG_SYNC (1 << 0) |
| 29 | |
Juan Quintela | ab7cbb0 | 2019-05-15 13:37:46 +0200 | [diff] [blame] | 30 | /* We reserve 3 bits for compression methods */ |
| 31 | #define MULTIFD_FLAG_COMPRESSION_MASK (7 << 1) |
| 32 | /* we need to be compatible. Before compression value was 0 */ |
| 33 | #define MULTIFD_FLAG_NOCOMP (0 << 1) |
Juan Quintela | 7ec2c2b | 2019-01-04 15:30:06 +0100 | [diff] [blame] | 34 | #define MULTIFD_FLAG_ZLIB (1 << 1) |
Juan Quintela | 87dc6f5 | 2019-12-13 13:47:14 +0100 | [diff] [blame] | 35 | #define MULTIFD_FLAG_ZSTD (2 << 1) |
Juan Quintela | ab7cbb0 | 2019-05-15 13:37:46 +0200 | [diff] [blame] | 36 | |
Juan Quintela | d32ca5a | 2020-01-22 16:16:07 +0100 | [diff] [blame] | 37 | /* This value needs to be a multiple of qemu_target_page_size() */ |
| 38 | #define MULTIFD_PACKET_SIZE (512 * 1024) |
| 39 | |
| 40 | typedef struct { |
| 41 | uint32_t magic; |
| 42 | uint32_t version; |
| 43 | uint32_t flags; |
| 44 | /* maximum number of allocated pages */ |
| 45 | uint32_t pages_alloc; |
Juan Quintela | 8c0ec0b | 2021-11-22 14:13:51 +0100 | [diff] [blame] | 46 | /* non zero pages */ |
| 47 | uint32_t normal_pages; |
Juan Quintela | d32ca5a | 2020-01-22 16:16:07 +0100 | [diff] [blame] | 48 | /* size of the next packet that contains pages */ |
| 49 | uint32_t next_packet_size; |
| 50 | uint64_t packet_num; |
| 51 | uint64_t unused[4]; /* Reserved for future use */ |
| 52 | char ramblock[256]; |
| 53 | uint64_t offset[]; |
| 54 | } __attribute__((packed)) MultiFDPacket_t; |
| 55 | |
| 56 | typedef struct { |
| 57 | /* number of used pages */ |
Juan Quintela | 90a3d2f | 2021-11-22 11:51:40 +0100 | [diff] [blame] | 58 | uint32_t num; |
Juan Quintela | d32ca5a | 2020-01-22 16:16:07 +0100 | [diff] [blame] | 59 | /* number of allocated pages */ |
| 60 | uint32_t allocated; |
| 61 | /* global number of generated multifd packets */ |
| 62 | uint64_t packet_num; |
| 63 | /* offset of each page */ |
| 64 | ram_addr_t *offset; |
Juan Quintela | d32ca5a | 2020-01-22 16:16:07 +0100 | [diff] [blame] | 65 | RAMBlock *block; |
| 66 | } MultiFDPages_t; |
| 67 | |
| 68 | typedef struct { |
Juan Quintela | 4a8f19c | 2022-05-31 12:43:06 +0200 | [diff] [blame] | 69 | /* Fields are only written at creating/deletion time */ |
| 70 | /* No lock required for them, they are read only */ |
| 71 | |
Juan Quintela | d32ca5a | 2020-01-22 16:16:07 +0100 | [diff] [blame] | 72 | /* channel number */ |
| 73 | uint8_t id; |
| 74 | /* channel thread name */ |
| 75 | char *name; |
| 76 | /* channel thread id */ |
| 77 | QemuThread thread; |
| 78 | /* communication channel */ |
| 79 | QIOChannel *c; |
Juan Quintela | 4a8f19c | 2022-05-31 12:43:06 +0200 | [diff] [blame] | 80 | /* is the yank function registered */ |
| 81 | bool registered_yank; |
| 82 | /* packet allocated len */ |
| 83 | uint32_t packet_len; |
Juan Quintela | ddec20f | 2022-05-02 16:45:35 +0200 | [diff] [blame] | 84 | /* guest page size */ |
| 85 | uint32_t page_size; |
Juan Quintela | d6f45eb | 2022-05-02 16:53:12 +0200 | [diff] [blame] | 86 | /* number of pages in a full packet */ |
| 87 | uint32_t page_count; |
Juan Quintela | 4a8f19c | 2022-05-31 12:43:06 +0200 | [diff] [blame] | 88 | /* multifd flags for sending ram */ |
| 89 | int write_flags; |
| 90 | |
Juan Quintela | d32ca5a | 2020-01-22 16:16:07 +0100 | [diff] [blame] | 91 | /* sem where to wait for more work */ |
| 92 | QemuSemaphore sem; |
Juan Quintela | 4a8f19c | 2022-05-31 12:43:06 +0200 | [diff] [blame] | 93 | /* syncs main thread and channels */ |
| 94 | QemuSemaphore sem_sync; |
| 95 | |
Juan Quintela | d32ca5a | 2020-01-22 16:16:07 +0100 | [diff] [blame] | 96 | /* this mutex protects the following parameters */ |
| 97 | QemuMutex mutex; |
| 98 | /* is this channel thread running */ |
| 99 | bool running; |
| 100 | /* should this thread finish */ |
| 101 | bool quit; |
Juan Quintela | d32ca5a | 2020-01-22 16:16:07 +0100 | [diff] [blame] | 102 | /* multifd flags for each packet */ |
| 103 | uint32_t flags; |
Juan Quintela | d32ca5a | 2020-01-22 16:16:07 +0100 | [diff] [blame] | 104 | /* global number of generated multifd packets */ |
| 105 | uint64_t packet_num; |
Juan Quintela | 4a8f19c | 2022-05-31 12:43:06 +0200 | [diff] [blame] | 106 | /* thread has work to do */ |
| 107 | int pending_job; |
| 108 | /* array of pages to sent. |
| 109 | * The owner of 'pages' depends of 'pending_job' value: |
| 110 | * pending_job == 0 -> migration_thread can use it. |
| 111 | * pending_job != 0 -> multifd_channel can use it. |
| 112 | */ |
| 113 | MultiFDPages_t *pages; |
| 114 | |
| 115 | /* thread local variables. No locking required */ |
| 116 | |
| 117 | /* pointer to the packet */ |
| 118 | MultiFDPacket_t *packet; |
| 119 | /* size of the next packet that contains pages */ |
| 120 | uint32_t next_packet_size; |
Juan Quintela | d32ca5a | 2020-01-22 16:16:07 +0100 | [diff] [blame] | 121 | /* packets sent through this channel */ |
| 122 | uint64_t num_packets; |
Juan Quintela | 815956f | 2021-11-22 13:26:18 +0100 | [diff] [blame] | 123 | /* non zero pages sent through this channel */ |
| 124 | uint64_t total_normal_pages; |
Juan Quintela | 226468b | 2021-11-19 12:06:05 +0100 | [diff] [blame] | 125 | /* buffers to send */ |
| 126 | struct iovec *iov; |
| 127 | /* number of iovs used */ |
| 128 | uint32_t iovs_num; |
Juan Quintela | 815956f | 2021-11-22 13:26:18 +0100 | [diff] [blame] | 129 | /* Pages that are not zero */ |
| 130 | ram_addr_t *normal; |
| 131 | /* num of non zero pages */ |
| 132 | uint32_t normal_num; |
Juan Quintela | ab7cbb0 | 2019-05-15 13:37:46 +0200 | [diff] [blame] | 133 | /* used for compression methods */ |
| 134 | void *data; |
Juan Quintela | d32ca5a | 2020-01-22 16:16:07 +0100 | [diff] [blame] | 135 | } MultiFDSendParams; |
| 136 | |
| 137 | typedef struct { |
Juan Quintela | 4a8f19c | 2022-05-31 12:43:06 +0200 | [diff] [blame] | 138 | /* Fields are only written at creating/deletion time */ |
| 139 | /* No lock required for them, they are read only */ |
| 140 | |
Juan Quintela | d32ca5a | 2020-01-22 16:16:07 +0100 | [diff] [blame] | 141 | /* channel number */ |
| 142 | uint8_t id; |
| 143 | /* channel thread name */ |
| 144 | char *name; |
| 145 | /* channel thread id */ |
| 146 | QemuThread thread; |
| 147 | /* communication channel */ |
| 148 | QIOChannel *c; |
Juan Quintela | 4a8f19c | 2022-05-31 12:43:06 +0200 | [diff] [blame] | 149 | /* packet allocated len */ |
| 150 | uint32_t packet_len; |
Juan Quintela | ddec20f | 2022-05-02 16:45:35 +0200 | [diff] [blame] | 151 | /* guest page size */ |
| 152 | uint32_t page_size; |
Juan Quintela | d6f45eb | 2022-05-02 16:53:12 +0200 | [diff] [blame] | 153 | /* number of pages in a full packet */ |
| 154 | uint32_t page_count; |
Juan Quintela | 4a8f19c | 2022-05-31 12:43:06 +0200 | [diff] [blame] | 155 | |
| 156 | /* syncs main thread and channels */ |
| 157 | QemuSemaphore sem_sync; |
| 158 | |
Juan Quintela | d32ca5a | 2020-01-22 16:16:07 +0100 | [diff] [blame] | 159 | /* this mutex protects the following parameters */ |
| 160 | QemuMutex mutex; |
| 161 | /* is this channel thread running */ |
| 162 | bool running; |
| 163 | /* should this thread finish */ |
| 164 | bool quit; |
Juan Quintela | d32ca5a | 2020-01-22 16:16:07 +0100 | [diff] [blame] | 165 | /* multifd flags for each packet */ |
| 166 | uint32_t flags; |
| 167 | /* global number of generated multifd packets */ |
| 168 | uint64_t packet_num; |
Juan Quintela | 4a8f19c | 2022-05-31 12:43:06 +0200 | [diff] [blame] | 169 | |
| 170 | /* thread local variables. No locking required */ |
| 171 | |
| 172 | /* pointer to the packet */ |
| 173 | MultiFDPacket_t *packet; |
Juan Quintela | d32ca5a | 2020-01-22 16:16:07 +0100 | [diff] [blame] | 174 | /* size of the next packet that contains pages */ |
| 175 | uint32_t next_packet_size; |
| 176 | /* packets sent through this channel */ |
| 177 | uint64_t num_packets; |
Lukas Straub | 5d1d1fc | 2023-05-08 21:11:07 +0200 | [diff] [blame] | 178 | /* ramblock */ |
| 179 | RAMBlock *block; |
Juan Quintela | 4a8f19c | 2022-05-31 12:43:06 +0200 | [diff] [blame] | 180 | /* ramblock host address */ |
| 181 | uint8_t *host; |
Juan Quintela | cf2d4aa | 2021-11-22 13:41:06 +0100 | [diff] [blame] | 182 | /* non zero pages recv through this channel */ |
| 183 | uint64_t total_normal_pages; |
Juan Quintela | 226468b | 2021-11-19 12:06:05 +0100 | [diff] [blame] | 184 | /* buffers to recv */ |
| 185 | struct iovec *iov; |
Juan Quintela | cf2d4aa | 2021-11-22 13:41:06 +0100 | [diff] [blame] | 186 | /* Pages that are not zero */ |
| 187 | ram_addr_t *normal; |
| 188 | /* num of non zero pages */ |
| 189 | uint32_t normal_num; |
Juan Quintela | ab7cbb0 | 2019-05-15 13:37:46 +0200 | [diff] [blame] | 190 | /* used for de-compression methods */ |
| 191 | void *data; |
Juan Quintela | d32ca5a | 2020-01-22 16:16:07 +0100 | [diff] [blame] | 192 | } MultiFDRecvParams; |
| 193 | |
Juan Quintela | ab7cbb0 | 2019-05-15 13:37:46 +0200 | [diff] [blame] | 194 | typedef struct { |
| 195 | /* Setup for sending side */ |
| 196 | int (*send_setup)(MultiFDSendParams *p, Error **errp); |
| 197 | /* Cleanup for sending side */ |
| 198 | void (*send_cleanup)(MultiFDSendParams *p, Error **errp); |
| 199 | /* Prepare the send packet */ |
Juan Quintela | 02fb810 | 2021-11-22 12:08:08 +0100 | [diff] [blame] | 200 | int (*send_prepare)(MultiFDSendParams *p, Error **errp); |
Juan Quintela | ab7cbb0 | 2019-05-15 13:37:46 +0200 | [diff] [blame] | 201 | /* Setup for receiving side */ |
| 202 | int (*recv_setup)(MultiFDRecvParams *p, Error **errp); |
| 203 | /* Cleanup for receiving side */ |
| 204 | void (*recv_cleanup)(MultiFDRecvParams *p); |
| 205 | /* Read all pages */ |
Juan Quintela | 40a4bfe | 2021-11-22 12:49:43 +0100 | [diff] [blame] | 206 | int (*recv_pages)(MultiFDRecvParams *p, Error **errp); |
Juan Quintela | ab7cbb0 | 2019-05-15 13:37:46 +0200 | [diff] [blame] | 207 | } MultiFDMethods; |
| 208 | |
Juan Quintela | 7ec2c2b | 2019-01-04 15:30:06 +0100 | [diff] [blame] | 209 | void multifd_register_ops(int method, MultiFDMethods *ops); |
| 210 | |
Juan Quintela | d32ca5a | 2020-01-22 16:16:07 +0100 | [diff] [blame] | 211 | #endif |
| 212 | |