xref: /qemu/migration/multifd.h (revision a2a63c4a)
1d32ca5adSJuan Quintela /*
2d32ca5adSJuan Quintela  * Multifd common functions
3d32ca5adSJuan Quintela  *
4d32ca5adSJuan Quintela  * Copyright (c) 2019-2020 Red Hat Inc
5d32ca5adSJuan Quintela  *
6d32ca5adSJuan Quintela  * Authors:
7d32ca5adSJuan Quintela  *  Juan Quintela <quintela@redhat.com>
8d32ca5adSJuan Quintela  *
9d32ca5adSJuan Quintela  * This work is licensed under the terms of the GNU GPL, version 2 or later.
10d32ca5adSJuan Quintela  * See the COPYING file in the top-level directory.
11d32ca5adSJuan Quintela  */
12d32ca5adSJuan Quintela 
13d32ca5adSJuan Quintela #ifndef QEMU_MIGRATION_MULTIFD_H
14d32ca5adSJuan Quintela #define QEMU_MIGRATION_MULTIFD_H
15d32ca5adSJuan Quintela 
16cde85c37SPeter Xu int multifd_send_setup(Error **errp);
17cde85c37SPeter Xu void multifd_send_shutdown(void);
18cde85c37SPeter Xu int multifd_recv_setup(Error **errp);
19cde85c37SPeter Xu void multifd_recv_cleanup(void);
20cde85c37SPeter Xu void multifd_recv_shutdown(void);
21d32ca5adSJuan Quintela bool multifd_recv_all_channels_created(void);
226720c2b3Smanish.mishra void multifd_recv_new_channel(QIOChannel *ioc, Error **errp);
23d32ca5adSJuan Quintela void multifd_recv_sync_main(void);
249346fa18SFabiano Rosas int multifd_send_sync_main(void);
25d6556d17SPeter Xu bool multifd_queue_page(RAMBlock *block, ram_addr_t offset);
26d32ca5adSJuan Quintela 
277ec2c2b3SJuan Quintela /* Multifd Compression flags */
28d32ca5adSJuan Quintela #define MULTIFD_FLAG_SYNC (1 << 0)
29d32ca5adSJuan Quintela 
30ab7cbb0bSJuan Quintela /* We reserve 3 bits for compression methods */
31ab7cbb0bSJuan Quintela #define MULTIFD_FLAG_COMPRESSION_MASK (7 << 1)
32ab7cbb0bSJuan Quintela /* we need to be compatible. Before compression value was 0 */
33ab7cbb0bSJuan Quintela #define MULTIFD_FLAG_NOCOMP (0 << 1)
347ec2c2b3SJuan Quintela #define MULTIFD_FLAG_ZLIB (1 << 1)
3587dc6f5fSJuan Quintela #define MULTIFD_FLAG_ZSTD (2 << 1)
36ab7cbb0bSJuan Quintela 
37d32ca5adSJuan Quintela /* This value needs to be a multiple of qemu_target_page_size() */
38d32ca5adSJuan Quintela #define MULTIFD_PACKET_SIZE (512 * 1024)
39d32ca5adSJuan Quintela 
40d32ca5adSJuan Quintela typedef struct {
41d32ca5adSJuan Quintela     uint32_t magic;
42d32ca5adSJuan Quintela     uint32_t version;
43d32ca5adSJuan Quintela     uint32_t flags;
44d32ca5adSJuan Quintela     /* maximum number of allocated pages */
45d32ca5adSJuan Quintela     uint32_t pages_alloc;
468c0ec0b2SJuan Quintela     /* non zero pages */
478c0ec0b2SJuan Quintela     uint32_t normal_pages;
48d32ca5adSJuan Quintela     /* size of the next packet that contains pages */
49d32ca5adSJuan Quintela     uint32_t next_packet_size;
50d32ca5adSJuan Quintela     uint64_t packet_num;
51d32ca5adSJuan Quintela     uint64_t unused[4];    /* Reserved for future use */
52d32ca5adSJuan Quintela     char ramblock[256];
53d32ca5adSJuan Quintela     uint64_t offset[];
54d32ca5adSJuan Quintela } __attribute__((packed)) MultiFDPacket_t;
55d32ca5adSJuan Quintela 
56d32ca5adSJuan Quintela typedef struct {
57d32ca5adSJuan Quintela     /* number of used pages */
5890a3d2f9SJuan Quintela     uint32_t num;
59d32ca5adSJuan Quintela     /* number of allocated pages */
60d32ca5adSJuan Quintela     uint32_t allocated;
61d32ca5adSJuan Quintela     /* offset of each page */
62d32ca5adSJuan Quintela     ram_addr_t *offset;
63d32ca5adSJuan Quintela     RAMBlock *block;
64d32ca5adSJuan Quintela } MultiFDPages_t;
65d32ca5adSJuan Quintela 
66d32ca5adSJuan Quintela typedef struct {
674a8f19c9SJuan Quintela     /* Fields are only written at creating/deletion time */
684a8f19c9SJuan Quintela     /* No lock required for them, they are read only */
694a8f19c9SJuan Quintela 
70d32ca5adSJuan Quintela     /* channel number */
71d32ca5adSJuan Quintela     uint8_t id;
72d32ca5adSJuan Quintela     /* channel thread name */
73d32ca5adSJuan Quintela     char *name;
74d32ca5adSJuan Quintela     /* channel thread id */
75d32ca5adSJuan Quintela     QemuThread thread;
76*a2a63c4aSFabiano Rosas     bool thread_created;
77e1921f10SFabiano Rosas     QemuThread tls_thread;
78e1921f10SFabiano Rosas     bool tls_thread_created;
79d32ca5adSJuan Quintela     /* communication channel */
80d32ca5adSJuan Quintela     QIOChannel *c;
814a8f19c9SJuan Quintela     /* is the yank function registered */
824a8f19c9SJuan Quintela     bool registered_yank;
834a8f19c9SJuan Quintela     /* packet allocated len */
844a8f19c9SJuan Quintela     uint32_t packet_len;
85ddec20f8SJuan Quintela     /* guest page size */
86ddec20f8SJuan Quintela     uint32_t page_size;
87d6f45ebaSJuan Quintela     /* number of pages in a full packet */
88d6f45ebaSJuan Quintela     uint32_t page_count;
894a8f19c9SJuan Quintela     /* multifd flags for sending ram */
904a8f19c9SJuan Quintela     int write_flags;
914a8f19c9SJuan Quintela 
92d32ca5adSJuan Quintela     /* sem where to wait for more work */
93d32ca5adSJuan Quintela     QemuSemaphore sem;
944a8f19c9SJuan Quintela     /* syncs main thread and channels */
954a8f19c9SJuan Quintela     QemuSemaphore sem_sync;
964a8f19c9SJuan Quintela 
97d32ca5adSJuan Quintela     /* multifd flags for each packet */
98d32ca5adSJuan Quintela     uint32_t flags;
99f5f48a78SPeter Xu     /*
100f5f48a78SPeter Xu      * The sender thread has work to do if either of below boolean is set.
101f5f48a78SPeter Xu      *
102f5f48a78SPeter Xu      * @pending_job:  a job is pending
103f5f48a78SPeter Xu      * @pending_sync: a sync request is pending
104f5f48a78SPeter Xu      *
105f5f48a78SPeter Xu      * For both of these fields, they're only set by the requesters, and
106f5f48a78SPeter Xu      * cleared by the multifd sender threads.
107f5f48a78SPeter Xu      */
108f5f48a78SPeter Xu     bool pending_job;
109f5f48a78SPeter Xu     bool pending_sync;
1104a8f19c9SJuan Quintela     /* array of pages to sent.
1114a8f19c9SJuan Quintela      * The owner of 'pages' depends of 'pending_job' value:
1124a8f19c9SJuan Quintela      * pending_job == 0 -> migration_thread can use it.
1134a8f19c9SJuan Quintela      * pending_job != 0 -> multifd_channel can use it.
1144a8f19c9SJuan Quintela      */
1154a8f19c9SJuan Quintela     MultiFDPages_t *pages;
1164a8f19c9SJuan Quintela 
1174a8f19c9SJuan Quintela     /* thread local variables. No locking required */
1184a8f19c9SJuan Quintela 
1194a8f19c9SJuan Quintela     /* pointer to the packet */
1204a8f19c9SJuan Quintela     MultiFDPacket_t *packet;
1214a8f19c9SJuan Quintela     /* size of the next packet that contains pages */
1224a8f19c9SJuan Quintela     uint32_t next_packet_size;
123d32ca5adSJuan Quintela     /* packets sent through this channel */
12405b7ec18SPeter Xu     uint64_t packets_sent;
125815956f0SJuan Quintela     /* non zero pages sent through this channel */
126815956f0SJuan Quintela     uint64_t total_normal_pages;
127226468baSJuan Quintela     /* buffers to send */
128226468baSJuan Quintela     struct iovec *iov;
129226468baSJuan Quintela     /* number of iovs used */
130226468baSJuan Quintela     uint32_t iovs_num;
131ab7cbb0bSJuan Quintela     /* used for compression methods */
132ab7cbb0bSJuan Quintela     void *data;
133d32ca5adSJuan Quintela }  MultiFDSendParams;
134d32ca5adSJuan Quintela 
135d32ca5adSJuan Quintela typedef struct {
1364a8f19c9SJuan Quintela     /* Fields are only written at creating/deletion time */
1374a8f19c9SJuan Quintela     /* No lock required for them, they are read only */
1384a8f19c9SJuan Quintela 
139d32ca5adSJuan Quintela     /* channel number */
140d32ca5adSJuan Quintela     uint8_t id;
141d32ca5adSJuan Quintela     /* channel thread name */
142d32ca5adSJuan Quintela     char *name;
143d32ca5adSJuan Quintela     /* channel thread id */
144d32ca5adSJuan Quintela     QemuThread thread;
145*a2a63c4aSFabiano Rosas     bool thread_created;
146d32ca5adSJuan Quintela     /* communication channel */
147d32ca5adSJuan Quintela     QIOChannel *c;
1484a8f19c9SJuan Quintela     /* packet allocated len */
1494a8f19c9SJuan Quintela     uint32_t packet_len;
150ddec20f8SJuan Quintela     /* guest page size */
151ddec20f8SJuan Quintela     uint32_t page_size;
152d6f45ebaSJuan Quintela     /* number of pages in a full packet */
153d6f45ebaSJuan Quintela     uint32_t page_count;
1544a8f19c9SJuan Quintela 
1554a8f19c9SJuan Quintela     /* syncs main thread and channels */
1564a8f19c9SJuan Quintela     QemuSemaphore sem_sync;
1574a8f19c9SJuan Quintela 
158d32ca5adSJuan Quintela     /* this mutex protects the following parameters */
159d32ca5adSJuan Quintela     QemuMutex mutex;
160d32ca5adSJuan Quintela     /* should this thread finish */
161d32ca5adSJuan Quintela     bool quit;
162d32ca5adSJuan Quintela     /* multifd flags for each packet */
163d32ca5adSJuan Quintela     uint32_t flags;
164d32ca5adSJuan Quintela     /* global number of generated multifd packets */
165d32ca5adSJuan Quintela     uint64_t packet_num;
1664a8f19c9SJuan Quintela 
1674a8f19c9SJuan Quintela     /* thread local variables. No locking required */
1684a8f19c9SJuan Quintela 
1694a8f19c9SJuan Quintela     /* pointer to the packet */
1704a8f19c9SJuan Quintela     MultiFDPacket_t *packet;
171d32ca5adSJuan Quintela     /* size of the next packet that contains pages */
172d32ca5adSJuan Quintela     uint32_t next_packet_size;
17305b7ec18SPeter Xu     /* packets received through this channel */
17405b7ec18SPeter Xu     uint64_t packets_recved;
1755d1d1fcfSLukas Straub     /* ramblock */
1765d1d1fcfSLukas Straub     RAMBlock *block;
1774a8f19c9SJuan Quintela     /* ramblock host address */
1784a8f19c9SJuan Quintela     uint8_t *host;
179cf2d4aa8SJuan Quintela     /* non zero pages recv through this channel */
180cf2d4aa8SJuan Quintela     uint64_t total_normal_pages;
181226468baSJuan Quintela     /* buffers to recv */
182226468baSJuan Quintela     struct iovec *iov;
183cf2d4aa8SJuan Quintela     /* Pages that are not zero */
184cf2d4aa8SJuan Quintela     ram_addr_t *normal;
185cf2d4aa8SJuan Quintela     /* num of non zero pages */
186cf2d4aa8SJuan Quintela     uint32_t normal_num;
187ab7cbb0bSJuan Quintela     /* used for de-compression methods */
188ab7cbb0bSJuan Quintela     void *data;
189d32ca5adSJuan Quintela } MultiFDRecvParams;
190d32ca5adSJuan Quintela 
191ab7cbb0bSJuan Quintela typedef struct {
192ab7cbb0bSJuan Quintela     /* Setup for sending side */
193ab7cbb0bSJuan Quintela     int (*send_setup)(MultiFDSendParams *p, Error **errp);
194ab7cbb0bSJuan Quintela     /* Cleanup for sending side */
195ab7cbb0bSJuan Quintela     void (*send_cleanup)(MultiFDSendParams *p, Error **errp);
196ab7cbb0bSJuan Quintela     /* Prepare the send packet */
19702fb8104SJuan Quintela     int (*send_prepare)(MultiFDSendParams *p, Error **errp);
198ab7cbb0bSJuan Quintela     /* Setup for receiving side */
199ab7cbb0bSJuan Quintela     int (*recv_setup)(MultiFDRecvParams *p, Error **errp);
200ab7cbb0bSJuan Quintela     /* Cleanup for receiving side */
201ab7cbb0bSJuan Quintela     void (*recv_cleanup)(MultiFDRecvParams *p);
202ab7cbb0bSJuan Quintela     /* Read all pages */
20340a4bfe9SJuan Quintela     int (*recv_pages)(MultiFDRecvParams *p, Error **errp);
204ab7cbb0bSJuan Quintela } MultiFDMethods;
205ab7cbb0bSJuan Quintela 
2067ec2c2b3SJuan Quintela void multifd_register_ops(int method, MultiFDMethods *ops);
20725a1f878SPeter Xu void multifd_send_fill_packet(MultiFDSendParams *p);
2087ec2c2b3SJuan Quintela 
209452b2057SPeter Xu static inline void multifd_send_prepare_header(MultiFDSendParams *p)
210452b2057SPeter Xu {
211452b2057SPeter Xu     p->iov[0].iov_len = p->packet_len;
212452b2057SPeter Xu     p->iov[0].iov_base = p->packet;
213452b2057SPeter Xu     p->iovs_num++;
214452b2057SPeter Xu }
215452b2057SPeter Xu 
216452b2057SPeter Xu 
217d32ca5adSJuan Quintela #endif
218