|  | /* | 
|  | * Multifd common functions | 
|  | * | 
|  | * Copyright (c) 2019-2020 Red Hat Inc | 
|  | * | 
|  | * Authors: | 
|  | *  Juan Quintela <quintela@redhat.com> | 
|  | * | 
|  | * This work is licensed under the terms of the GNU GPL, version 2 or later. | 
|  | * See the COPYING file in the top-level directory. | 
|  | */ | 
|  |  | 
|  | #ifndef QEMU_MIGRATION_MULTIFD_H | 
|  | #define QEMU_MIGRATION_MULTIFD_H | 
|  |  | 
|  | int multifd_save_setup(Error **errp); | 
|  | void multifd_save_cleanup(void); | 
|  | int multifd_load_setup(Error **errp); | 
|  | void multifd_load_cleanup(void); | 
|  | void multifd_load_shutdown(void); | 
|  | bool multifd_recv_all_channels_created(void); | 
|  | void multifd_recv_new_channel(QIOChannel *ioc, Error **errp); | 
|  | void multifd_recv_sync_main(void); | 
|  | int multifd_send_sync_main(QEMUFile *f); | 
|  | int multifd_queue_page(QEMUFile *f, RAMBlock *block, ram_addr_t offset); | 
|  |  | 
|  | /* Multifd Compression flags */ | 
|  | #define MULTIFD_FLAG_SYNC (1 << 0) | 
|  |  | 
|  | /* We reserve 3 bits for compression methods */ | 
|  | #define MULTIFD_FLAG_COMPRESSION_MASK (7 << 1) | 
|  | /* we need to be compatible. Before compression value was 0 */ | 
|  | #define MULTIFD_FLAG_NOCOMP (0 << 1) | 
|  | #define MULTIFD_FLAG_ZLIB (1 << 1) | 
|  | #define MULTIFD_FLAG_ZSTD (2 << 1) | 
|  |  | 
|  | /* This value needs to be a multiple of qemu_target_page_size() */ | 
|  | #define MULTIFD_PACKET_SIZE (512 * 1024) | 
|  |  | 
|  | typedef struct { | 
|  | uint32_t magic; | 
|  | uint32_t version; | 
|  | uint32_t flags; | 
|  | /* maximum number of allocated pages */ | 
|  | uint32_t pages_alloc; | 
|  | /* non zero pages */ | 
|  | uint32_t normal_pages; | 
|  | /* size of the next packet that contains pages */ | 
|  | uint32_t next_packet_size; | 
|  | uint64_t packet_num; | 
|  | uint64_t unused[4];    /* Reserved for future use */ | 
|  | char ramblock[256]; | 
|  | uint64_t offset[]; | 
|  | } __attribute__((packed)) MultiFDPacket_t; | 
|  |  | 
|  | typedef struct { | 
|  | /* number of used pages */ | 
|  | uint32_t num; | 
|  | /* number of allocated pages */ | 
|  | uint32_t allocated; | 
|  | /* global number of generated multifd packets */ | 
|  | uint64_t packet_num; | 
|  | /* offset of each page */ | 
|  | ram_addr_t *offset; | 
|  | RAMBlock *block; | 
|  | } MultiFDPages_t; | 
|  |  | 
|  | typedef struct { | 
|  | /* Fields are only written at creating/deletion time */ | 
|  | /* No lock required for them, they are read only */ | 
|  |  | 
|  | /* channel number */ | 
|  | uint8_t id; | 
|  | /* channel thread name */ | 
|  | char *name; | 
|  | /* channel thread id */ | 
|  | QemuThread thread; | 
|  | /* communication channel */ | 
|  | QIOChannel *c; | 
|  | /* is the yank function registered */ | 
|  | bool registered_yank; | 
|  | /* packet allocated len */ | 
|  | uint32_t packet_len; | 
|  | /* guest page size */ | 
|  | uint32_t page_size; | 
|  | /* number of pages in a full packet */ | 
|  | uint32_t page_count; | 
|  | /* multifd flags for sending ram */ | 
|  | int write_flags; | 
|  |  | 
|  | /* sem where to wait for more work */ | 
|  | QemuSemaphore sem; | 
|  | /* syncs main thread and channels */ | 
|  | QemuSemaphore sem_sync; | 
|  |  | 
|  | /* this mutex protects the following parameters */ | 
|  | QemuMutex mutex; | 
|  | /* is this channel thread running */ | 
|  | bool running; | 
|  | /* should this thread finish */ | 
|  | bool quit; | 
|  | /* multifd flags for each packet */ | 
|  | uint32_t flags; | 
|  | /* global number of generated multifd packets */ | 
|  | uint64_t packet_num; | 
|  | /* thread has work to do */ | 
|  | int pending_job; | 
|  | /* array of pages to sent. | 
|  | * The owner of 'pages' depends of 'pending_job' value: | 
|  | * pending_job == 0 -> migration_thread can use it. | 
|  | * pending_job != 0 -> multifd_channel can use it. | 
|  | */ | 
|  | MultiFDPages_t *pages; | 
|  |  | 
|  | /* thread local variables. No locking required */ | 
|  |  | 
|  | /* pointer to the packet */ | 
|  | MultiFDPacket_t *packet; | 
|  | /* size of the next packet that contains pages */ | 
|  | uint32_t next_packet_size; | 
|  | /* packets sent through this channel */ | 
|  | uint64_t num_packets; | 
|  | /* non zero pages sent through this channel */ | 
|  | uint64_t total_normal_pages; | 
|  | /* buffers to send */ | 
|  | struct iovec *iov; | 
|  | /* number of iovs used */ | 
|  | uint32_t iovs_num; | 
|  | /* Pages that are not zero */ | 
|  | ram_addr_t *normal; | 
|  | /* num of non zero pages */ | 
|  | uint32_t normal_num; | 
|  | /* used for compression methods */ | 
|  | void *data; | 
|  | }  MultiFDSendParams; | 
|  |  | 
|  | typedef struct { | 
|  | /* Fields are only written at creating/deletion time */ | 
|  | /* No lock required for them, they are read only */ | 
|  |  | 
|  | /* channel number */ | 
|  | uint8_t id; | 
|  | /* channel thread name */ | 
|  | char *name; | 
|  | /* channel thread id */ | 
|  | QemuThread thread; | 
|  | /* communication channel */ | 
|  | QIOChannel *c; | 
|  | /* packet allocated len */ | 
|  | uint32_t packet_len; | 
|  | /* guest page size */ | 
|  | uint32_t page_size; | 
|  | /* number of pages in a full packet */ | 
|  | uint32_t page_count; | 
|  |  | 
|  | /* syncs main thread and channels */ | 
|  | QemuSemaphore sem_sync; | 
|  |  | 
|  | /* this mutex protects the following parameters */ | 
|  | QemuMutex mutex; | 
|  | /* is this channel thread running */ | 
|  | bool running; | 
|  | /* should this thread finish */ | 
|  | bool quit; | 
|  | /* multifd flags for each packet */ | 
|  | uint32_t flags; | 
|  | /* global number of generated multifd packets */ | 
|  | uint64_t packet_num; | 
|  |  | 
|  | /* thread local variables. No locking required */ | 
|  |  | 
|  | /* pointer to the packet */ | 
|  | MultiFDPacket_t *packet; | 
|  | /* size of the next packet that contains pages */ | 
|  | uint32_t next_packet_size; | 
|  | /* packets sent through this channel */ | 
|  | uint64_t num_packets; | 
|  | /* ramblock */ | 
|  | RAMBlock *block; | 
|  | /* ramblock host address */ | 
|  | uint8_t *host; | 
|  | /* non zero pages recv through this channel */ | 
|  | uint64_t total_normal_pages; | 
|  | /* buffers to recv */ | 
|  | struct iovec *iov; | 
|  | /* Pages that are not zero */ | 
|  | ram_addr_t *normal; | 
|  | /* num of non zero pages */ | 
|  | uint32_t normal_num; | 
|  | /* used for de-compression methods */ | 
|  | void *data; | 
|  | } MultiFDRecvParams; | 
|  |  | 
|  | typedef struct { | 
|  | /* Setup for sending side */ | 
|  | int (*send_setup)(MultiFDSendParams *p, Error **errp); | 
|  | /* Cleanup for sending side */ | 
|  | void (*send_cleanup)(MultiFDSendParams *p, Error **errp); | 
|  | /* Prepare the send packet */ | 
|  | int (*send_prepare)(MultiFDSendParams *p, Error **errp); | 
|  | /* Setup for receiving side */ | 
|  | int (*recv_setup)(MultiFDRecvParams *p, Error **errp); | 
|  | /* Cleanup for receiving side */ | 
|  | void (*recv_cleanup)(MultiFDRecvParams *p); | 
|  | /* Read all pages */ | 
|  | int (*recv_pages)(MultiFDRecvParams *p, Error **errp); | 
|  | } MultiFDMethods; | 
|  |  | 
|  | void multifd_register_ops(int method, MultiFDMethods *ops); | 
|  |  | 
|  | #endif | 
|  |  |