1
2
3
4
5
6
7
8
9
10
11
12
13#include "qemu/osdep.h"
14#include "qemu/cutils.h"
15#include "system/ramblock.h"
16#include "migration.h"
17#include "migration-stats.h"
18#include "multifd.h"
19#include "options.h"
20#include "ram.h"
21
22static bool multifd_zero_page_enabled(void)
23{
24 return migrate_zero_page_detection() == ZERO_PAGE_DETECTION_MULTIFD;
25}
26
27static void swap_page_offset(ram_addr_t *pages_offset, int a, int b)
28{
29 ram_addr_t temp;
30
31 if (a == b) {
32 return;
33 }
34
35 temp = pages_offset[a];
36 pages_offset[a] = pages_offset[b];
37 pages_offset[b] = temp;
38}
39
40
41
42
43
44
45
46
47
48void multifd_send_zero_page_detect(MultiFDSendParams *p)
49{
50 MultiFDPages_t *pages = &p->data->u.ram;
51 RAMBlock *rb = pages->block;
52 int i = 0;
53 int j = pages->num - 1;
54
55 if (!multifd_zero_page_enabled()) {
56 pages->normal_num = pages->num;
57 goto out;
58 }
59
60
61
62
63
64 while (i <= j) {
65 uint64_t offset = pages->offset[i];
66
67 if (!buffer_is_zero(rb->host + offset, multifd_ram_page_size())) {
68 i++;
69 continue;
70 }
71
72 swap_page_offset(pages->offset, i, j);
73 ram_release_page(rb->idstr, offset);
74 j--;
75 }
76
77 pages->normal_num = i;
78
79out:
80 stat64_add(&mig_stats.normal_pages, pages->normal_num);
81 stat64_add(&mig_stats.zero_pages, pages->num - pages->normal_num);
82}
83
84void multifd_recv_zero_page_process(MultiFDRecvParams *p)
85{
86 for (int i = 0; i < p->zero_num; i++) {
87 void *page = p->host + p->zero[i];
88 bool received =
89 ramblock_recv_bitmap_test_byte_offset(p->block, p->zero[i]);
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105 if (migrate_postcopy_ram() || received) {
106 memset(page, 0, multifd_ram_page_size());
107 }
108 if (!received) {
109 ramblock_recv_bitmap_set_offset(p->block, p->zero[i]);
110 }
111 }
112}
113